nyoj 谍战 (最小割最大流)

做完图论学网络流。。  不会先转了。。

转自http://blog.csdn.net/AQ14AQ1/article/details/38866407

如果能想到是最小割问题,那么建图思路便是水到渠成的事了。

添加一个源点S和汇点T;

把S与每个间谍相连,容量为无穷大;

把城市N(即飞机场的位置)与汇点T相连,容量为无穷大;

之间有道路的城市相连,容量为1,注意这里是双向的边;

建图完后,根据最大流最小割定理,那么直接求最大流即可。

  1 #include<iostream>
  2 using namespace std;
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<string>
  8 #include<queue>
  9 #include<stack>
 10 #include<map>
 11 #include<vector>
 12 #include<algorithm>
 13 
 14 #define INS 1<<30
 15 #define CLR(arr,v) memset(arr,v,sizeof(arr))
 16 
 17 #define MaxV 3000
 18 #define MaxE 100000
 19 
 20 class MaxFlow{
 21 public:
 22     void Clear(){
 23         CLR(h,-1); CLR(cnt,0); CLR(vis,0);
 24         flag = false;
 25         pos = top = head = total = maxflow = 0;
 26     }
 27     void add(int u,int v,int flow){
 28         num[pos] = v;
 29         sur[pos] = flow;
 30         next[pos] = h[u];
 31         h[u] = pos++;
 32 
 33         num[pos] = u;
 34         sur[pos] = 0;
 35         next[pos] = h[v];
 36         h[v] = pos++;
 37     }
 38     int GetMaxFlow(int s,int t){
 39         init(t);
 40         stk[top] = s;
 41         while(!flag){
 42             minres = INS;
 43             if(top < 0) top = 0;
 44             if(!dfs(stk[top],-1,t,minres)) continue;
 45             maxflow += minres;
 46             while(dis != -1){
 47                 sur[dis] -= minres;
 48                 sur[dis^1] += minres;
 49                 dis = pre_e[dis];
 50             }
 51             top = 0;
 52         }
 53         return maxflow;
 54     }
 55 private:
 56     int h[MaxV],num[MaxE],sur[MaxE],next[MaxE],gap[MaxV],cnt[MaxV],pre_e[MaxE],stk[MaxV],que[MaxV];
 57     int pos,top,head,total,maxflow,minres,dis;
 58     bool vis[MaxV],flag;
 59     void init(int n){
 60         que[total++] = n;
 61         vis[n] = true;
 62         while(head < total){
 63             int p = que[head++];
 64             if(head >= MaxV) head -= MaxV;
 65             for(int i = h[p]; i != -1 ;i = next[i]){
 66                 if(!vis[ num[i] ]){
 67                     vis[ num[i] ] = true;
 68                     gap[ num[i] ] = gap[p] + 1;
 69                     cnt[ gap[ num[i] ] ]++;
 70                     que[total++] = num[i];
 71                     if(total >= MaxV) total -= MaxV;
 72                 }
 73             }
 74         }
 75     }
 76     bool dfs(int p,int father,int n,int &minres){
 77         int m = minres;
 78         for(int i = h[p]; i != -1 ;i = next[i]){
 79             if(sur[i] > 0 && gap[p] - gap[ num[i] ] == 1){
 80                 minres = min(minres,sur[i]);
 81                 pre_e[i] = father;
 82                 if(num[i] != n) stk[++top] = num[i];
 83                 if(num[i] == n || dfs(num[i],i,n,minres)) {
 84                     if(num[i] == n) dis = i;
 85                     return true;
 86                 }
 87                 minres = m;
 88             }
 89         }
 90         cnt[ gap[p] ]--;
 91         cnt[ gap[p] + 1]++;
 92         top--;
 93         if(cnt[ gap[p] ] == 0) flag = true;
 94         gap[p] += 1;
 95         return false;
 96     }
 97 }T;
 98 
 99 
100 int main()
101 {   
102     int t;
103     scanf("%d",&t);
104     int cnt = 0;
105     while (t--)
106           {
107           int n,m,p;
108           scanf("%d%d%d",&n,&m,&p);
109           
110           int N = n + 1;
111           T.Clear();
112           
113           int x;
114           for (int i = 1; i <= p; ++ i)
115                scanf("%d",&x),T.add(0,x,INS);
116           
117           for (int i = 1; i <= m; ++ i)
118               {
119               int u,v;
120               scanf("%d%d",&u,&v);     
121               T.add(u,v,1);
122               T.add(v,u,1);
123               }
124           
125           T.add(n,N,INS);
126     
127           printf("Case #%d: %d
",++cnt,T.GetMaxFlow(0,N));
128           }
129     return 0;
130 }
原文地址:https://www.cnblogs.com/usedrosee/p/4337696.html