BZOJ1458 士兵占領 最大流

2021-07-22 17:43:41 字數 1541 閱讀 9675

time limit: 10 sec  

memory limit: 64 mb

submit: 917  

solved: 515 [

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

題目顯然可以用網路流來求解:

因為想要得到最少需要擺放的士兵,我們可以轉化一下問題去求最多有多少個格仔不能放

我們可以把所有列,所有行抽象成n+m個點,把每一行向源點連一條邊

邊權是:對於每一行看看有多少個位置可以放士兵(也就是假設每排可以放m個士兵,這排有x個地方不能放士兵,這排要求必須要放y,邊權就是m-x-y),對於每一列也是同理。

然後我們再搜尋整個棋盤,比如座標(x,y)處可以放棋子,就將行x所代表的點和列y所代表的點連一條邊,邊權為1,跑最大流就可以了,最大流的意義就是最多能找到多少個點可以不放棋子

答案ans=(n*m-k-最大流)

#include#include#include#includeusing namespace std;

const int n=305;

const int m=40005;

const int inf=2100000000;

int c[n],l[n],n,m,k,nl[n],nc[n],ans,mp[n][n];

int from[m],to[m],nxt[m],lj[n],cnt=-1,w[m],pre[n];

void add(int f,int t,int p)

int s,t,d[n];

queueq;

bool bfs()

} if(d[t]) return true;

return false;

}int dfs(int x,int v)

return ret;

}void make()

int main()

make();

for(int i=0;i<=cnt;i++)

if(w[i]<0)

while(bfs()) ans+=dfs(s,inf);

printf("%d",n*m-k-ans);

}

BZOJ1458 士兵占領(最大流)

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

bzoj1458 士兵占領 最大流

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

bzoj1458 士兵占領 最大流

time limit 10 sec memory limit 64 mb submit status discuss 有乙個m n的棋盤,有的格仔是障礙。現在你要選擇一些格仔來放置一些士兵,乙個格仔裡最多可以放置乙個士兵,障礙格里不能放置士兵。我們稱這些士兵占領了整個棋盤當滿足第i行至少放置了li個...