【BZOJ-1458】士兵占领 最大流
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ-1458】士兵占领 最大流
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1458: 士兵占領
Time Limit:?10 Sec??Memory Limit:?64 MBSubmit:?782??Solved:?456
[Submit][Status][Discuss]
Description
有一個M * N的棋盤,有的格子是障礙。現在你要選擇一些格子來放置一些士兵,一個格子里最多可以放置一個士兵,障礙格里不能放置士兵。我們稱這些士兵占領了整個棋盤當滿足第i行至少放置了Li個士兵, 第j列至少放置了Cj個士兵。現在你的任務是要求使用最少個數的士兵來占領整個棋盤。
Input
第一行兩個數M, N, K分別表示棋盤的行數,列數以及障礙的個數。 第二行有M個數表示Li。 第三行有N個數表示Ci。 接下來有K行,每行兩個數X, Y表示(X, Y)這個格子是障礙。
Output
輸出一個數表示最少需要使用的士兵個數。如果無論放置多少個士兵都沒有辦法占領整個棋盤,輸出”JIONG!” (不含引號)
Sample Input
4 4 41 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
Sample Output
4數據范圍
M, N <= 100, 0 <= K <= M * N
HINT
Source
Solution
仰慕黃學長....
把題目轉化一下,使用最少的,轉換成刪去最多的,那么可用最大流求解
對于某行或某列,如果可以放的個數小于必須放的個數,那么直接JIONG!
那么對于源向各行連邊,容量為可以放的格子數 – 需求的格子數
對于各列向匯連邊,容量同上
從可放置的點的行連至列,容量為1
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read() {int x=0,f=1; char ch=getchar();while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}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 Edgenode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) {cnt++;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].cap=w;} void insert(int u,int v,int w) {add(u,v,w);add(v,u,0);} // int q[maxn],dis[maxn],cur[maxn]; bool bfs() {for (int i=S; i<=T; i++) dis[i]=-1;int he=0,ta=1; q[0]=S; dis[S]=0;while (he<ta){int now=q[he++];for (int i=head[now]; i; i=edge[i].next)if (edge[i].cap && dis[edge[i].to]==-1){dis[edge[i].to]=dis[now]+1;q[ta++]=edge[i].to;}}return dis[T]!=-1; } int dfs(int loc,int low) {if (loc==T) return low;int w,used=0;for (int i=cur[loc]; i; i=edge[i].next)if (edge[i].cap && dis[edge[i].to]==dis[loc]+1){w=dfs(edge[i].to,min(low-used,edge[i].cap));edge[i].cap-=w; edge[i^1].cap+=w;used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low;}if (!used) dis[loc]=-1;return used; } #define inf 0x7fffffff int dinic() {int tmp=0;while (bfs()){for (int i=S; i<=T; i++) cur[i]=head[i];tmp+=dfs(S,inf);}return tmp; } void make() {S=0,T=n+m+1;for (int i=1; i<=m; i++)insert(S,i,n-L[i]-hang[i]);for (int i=1; i<=n; i++)insert(i+m,T,m-C[i]-lie[T]);for (int i=1; i<=m; i++)for (int j=1; j<=n; j++)if (!zt[i][j]) insert(i,j+m,1); } int main() {m=read(),n=read(),k=read();for (int i=1; i<=m; i++) L[i]=read();for (int i=1; i<=n; i++) C[i]=read();tot=n*m-k;for (int x,y,i=1; i<=k; i++) x=read(),y=read(),hang[x]++,lie[y]++,zt[x][y]=1;for (int i=1; i<=m; i++)if (hang[i]>n-L[i]) {puts("JIONG!");return 0;}for (int i=1; i<=n; i++)if (lie[i]>m-C[i]) {puts("JIONG!");return 0;}make();ans=dinic();printf("%d\n",tot-ans);return 0; }好厲害...一開始沒想到...看到這種網格圖,就想黑白染色QAQ
轉載于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5357683.html
總結
以上是生活随笔為你收集整理的【BZOJ-1458】士兵占领 最大流的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 矩阵的运算及其运算规则
- 下一篇: 【C语言重点难点精讲】C语言文件