【bzoj1458】士兵占领(最大流||有源汇最大流)
转载
http://hzwer.com/2963.html
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 4
1 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
1 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
数据范围
M, N <= 100, 0 <= K <= M * N
题解
此题的思路是先放满棋盘,然后考虑最多可以删多少个。。。
某一行和某一列的可以放的格子数小于需求就直接jiong掉
然后从源向每一行连边,流量为可以放的格子数 – 需求的格子数(也就是可以删多少格子)
从每一列向汇,同上.
从每一个非障碍的格子的行向列连边流量为1
跑一遍最大流即可ans=可放格子数-maxflow
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #define T 201 6 #define inf 0x7fffffff 7 inline int read() 8 { 9 char ch=getchar(); 10 int f=1,x=0; 11 while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();} 13 return x*f; 14 } 15 using namespace std; 16 int n,m,K,cnt=1,tot,ans; 17 int l[105],c[105],a[105],b[105]; 18 bool mp[105][105]; 19 int q[205],h[205],head[205],cur[205]; 20 struct data{int to,next,v;}e[100001]; 21 void ins(int u,int v,int w) 22 {e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;} 23 void insert(int u,int v,int w) 24 {ins(u,v,w);ins(v,u,0);} 25 bool bfs() 26 { 27 int t=0,w=1; 28 for(int i=0;i<=T;i++)h[i]=-1; 29 q[0]=0;h[0]=0; 30 while(t!=w) 31 { 32 int now=q[t];t++; 33 for(int i=head[now];i;i=e[i].next) 34 if(e[i].v&&h[e[i].to]==-1) 35 { 36 h[e[i].to]=h[now]+1; 37 q[w++]=e[i].to; 38 } 39 } 40 if(h[T]==-1)return 0; 41 return 1; 42 } 43 int dfs(int x,int f) 44 { 45 if(x==T)return f; 46 int w,used=0; 47 for(int i=cur[x];i;i=e[i].next) 48 { 49 if(e[i].v&&h[e[i].to]==h[x]+1) 50 { 51 w=f-used; 52 w=dfs(e[i].to,min(e[i].v,w)); 53 e[i].v-=w; 54 if(e[i].v)cur[x]=i; 55 e[i^1].v+=w; 56 used+=w;if(used==f)return f; 57 } 58 } 59 if(!used)h[x]=-1; 60 return used; 61 } 62 void dinic() 63 {while(bfs()){for(int i=0;i<=T;i++)cur[i]=head[i];ans+=dfs(0,inf);}} 64 int main() 65 { 66 m=read();n=read();K=read(); 67 int x,y; 68 for(int i=1;i<=m;i++) 69 l[i]=n-read(); 70 for(int i=1;i<=n;i++) 71 c[i]=m-read(); 72 for(int i=1;i<=K;i++) 73 { 74 x=read();y=read(); 75 mp[x][y]=1; 76 a[x]++;b[y]++; 77 if(a[x]>l[x]){printf("JIONG!");return 0;} 78 if(b[y]>c[y]){printf("JIONG!");return 0;} 79 } 80 tot=n*m-K; 81 for(int i=1;i<=m;i++) 82 insert(0,i,l[i]-a[i]); 83 for(int i=1;i<=n;i++) 84 insert(m+i,T,c[i]-b[i]); 85 for(int i=1;i<=m;i++) 86 for(int j=1;j<=n;j++) 87 if(!mp[i][j])insert(i,j+m,1); 88 dinic(); 89 printf("%d",tot-ans); 90 return 0; 91 }
1 #include <stdio.h> 2 #include <iostream> 3 #include <algorithm> 4 #include <memory.h> 5 #include <map> 6 7 using namespace std; 8 typedef long long LL; 9 const int maxn = 400005; 10 const int maxm = 105; 11 const int inf = 1<<30; 12 13 int n,m,K,S,T,cnt,ecnt=1,ehead[maxn],du[maxn]; 14 int g[maxm][maxm],row[maxn],col[maxn]; 15 16 struct edge { 17 int u,v,vol,next; 18 }edg[maxn]; 19 void add(int u,int v,int vol) 20 { 21 edg[++ecnt]=(edge){u,v,vol,ehead[u]}; 22 ehead[u]=ecnt; 23 edg[++ecnt]=(edge){v,u,0,ehead[v]}; 24 ehead[v]=ecnt; 25 } 26 27 namespace dinic 28 { 29 int lab[maxn],que[maxn],head,tail; 30 int dfs(int u,int cur,int T) 31 { 32 int res=0; 33 if (u==T) return cur; 34 for (int v,j=ehead[u];j&&res<cur;j=edg[j].next) 35 if (edg[j].vol&&lab[v=edg[j].v]==lab[u]+1) { 36 int tmp=dfs(v,min(cur-res,edg[j].vol),T); 37 edg[j].vol-=tmp;edg[j^1].vol+=tmp;res+=tmp; 38 } 39 if (!res) lab[u]=-1; 40 return res; 41 } 42 bool bfs(int S,int T) 43 { 44 memset(lab,-1,sizeof(int)*(cnt+1)); 45 que[head=tail=0]=S;lab[S]=0; 46 while (head<=tail) 47 { 48 int u=que[head++]; 49 for (int v,j=ehead[u];j;j=edg[j].next) 50 if (edg[j].vol&&lab[v=edg[j].v]==-1) 51 {lab[v]=lab[u]+1;que[++tail]=v;} 52 } 53 return lab[T]!=-1; 54 } 55 int dinic(int S,int T) 56 { 57 int res=0; 58 while (bfs(S,T)) res+=dfs(S,inf,T); 59 return res; 60 } 61 int main() 62 { 63 int sS=++cnt,sT=++cnt; 64 int ocnt=ecnt; 65 for (int i=1;i<sS;i++) 66 { 67 if (du[i]>0) add(i,sT,du[i]); 68 if (du[i]<0) add(sS,i,-du[i]); 69 } 70 add(T,S,inf);dinic(sS,sT); 71 int res=edg[ecnt].vol; 72 for (int j=ehead[sS];j;j=edg[j].next) 73 if (edg[j].vol) return -1; 74 for (int j=ocnt+1;j<=ecnt;j++) 75 edg[j].vol=0; 76 return res-dinic(T,S); 77 78 } 79 } 80 int main() 81 { 82 scanf("%d %d %d",&n,&m,&K); 83 S=++cnt;T=++cnt; 84 for (int i=1;i<=n;i++) row[i]=++cnt; 85 for (int i=1;i<=m;i++) col[i]=++cnt; 86 for (int x,i=1;i<=n;i++) 87 scanf("%d",&x),du[row[i]]-=x,du[S]+=x,add(S,row[i],m); 88 for (int x,i=1;i<=m;i++) 89 scanf("%d",&x),du[col[i]]+=x,du[T]-=x,add(col[i],T,n); 90 for (int u,v,i=1;i<=K;i++) 91 scanf("%d %d",&u,&v),g[u][v]=1; 92 for (int i=1;i<=n;i++) 93 for (int j=1;j<=m;j++) 94 if (!g[i][j]) add(row[i],col[j],1); 95 int ans=dinic::main(); 96 if (ans!=-1) printf("%d",ans);else puts("No Solution"); 97 return 0; 98 }