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\n",++cnt,T.GetMaxFlow(0,N)); 128 } 129 return 0; 130 }