BZOJ 1458 士兵占領 最大流

2022-05-20 09:35:46 字數 1771 閱讀 8765

time limit: 10 sec  memory limit: 64 mb

submit: 782  solved: 456

[submit][status][discuss]

有乙個m * n的棋盤,有的格仔是障礙。現在你要選擇一些格仔來放置一些士兵,乙個格仔裡最多可以放置乙個士兵,障礙格里不能放置士兵。我們稱這些士兵占領了整個棋盤當滿足第i行至少放置了li個士兵, 第j列至少放置了cj個士兵。現在你的任務是要求使用最少個數的士兵來占領整個棋盤。

第一行兩個數m, n, k分別表示棋盤的行數,列數以及障礙的個數。 第二行有m個數表示li。 第三行有n個數表示ci。 接下來有k行,每行兩個數x, y表示(x, y)這個格仔是障礙。

輸出乙個數表示最少需要使用的士兵個數。如果無論放置多少個士兵都沒有辦法占領整個棋盤,輸出」jiong!」 (不含引號)

4 4 4

1 1 1 1

0 1 0 3

1 42 2

3 34 3

4資料範圍

m, n <= 100, 0 <= k <= m * n

仰慕黃學長....

把題目轉化一下,使用最少的,轉換成刪去最多的,那麼可用最大流求解

對於某行或某列,如果可以放的個數小於必須放的個數,那麼直接jiong!

那麼對於源向各行連邊,容量為可以放的格仔數 – 需求的格仔數

對於各列向匯連邊,容量同上

從可放置的點的行連至列,容量為1

#include#include

#include

#include

#include

using

namespace

std;

intread()

while (ch>='

0' && ch<='

9')

return x*f;

}#define maxm 20000

#define maxn 500

int n,m,k;int l[110],c[110

];int zt[110][110

];int hang[110],lie[110

],ans,tot,s,t;

struct edgenodeedge[maxm];

int head[maxn],cnt=1

;void add(int u,int v,int

w)void insert(int u,int v,int

w)//

intq[maxn],dis[maxn],cur[maxn];

bool

bfs()

}return dis[t]!=-1;}

int dfs(int loc,int

low)

if (!used) dis[loc]=-1

;

return

used;

}#define inf 0x7fffffff

intdinic()

return

tmp;

}void

make()

intmain()

for (int i=1; i<=n; i++)

if (lie[i]>m-c[i])

make();

ans=dinic();

printf(

"%d\n

",tot-ans);

return0;

}

好厲害...一開始沒想到...看到這種網格圖,就想黑白染色qaq

BZOJ1458 士兵占領(最大流)

傳送門 判斷joing 的條件是顯然的 如果行或列的總點數減去障礙數還不夠li或ci的話,肯定無解。我的建圖比較奇怪。三排點,分別為每一行,每個點,每一列。s 每一行,li 每一列 t,ci 每一行 當前行中的點,1 每個點 所在的列,1 注意這裡的點必須不是障礙點。最大流即為答案。貼上hzwer的...

BZOJ1458 士兵占領 最大流

time limit 10 sec memory limit 64 mb submit 917 solved 515 submit status discuss 有乙個m n的棋盤,有的格仔是障礙。現在你要選擇一些格仔來放置一些士兵,乙個格仔裡最多可以放置乙個士兵,障礙格里不能放置士兵。我們稱這些士...

bzoj1458 士兵占領 最大流

又是反過來考慮。直接計算會很複雜 畢竟每一行和每一列都會有一定的限制條件,很難同時滿足 那麼我們放過來思考,先把所有的各自都放上士兵一共n m k個,然後考慮拿走一部分士兵。源點向每行建邊,邊權是 m l i 這一行的障礙格仔數目,即是能夠拿走的士兵數目,然後列向匯點建邊,同理,每乙個格仔 可拿走 ...