【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

Sample Output

4
数据范围
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 }

 

posted @ 2017-10-18 21:40  抓不住Jerry的Tom  阅读(190)  评论(0编辑  收藏  举报