最小割的相关知识请参见:网络流问题
I. hdu4289 Control
题意:给出一个由n个点,m条边组成的无向图。给出两个点s,t。对于图中的每个点,去掉这个点都需要一定的花费。求至少多少花费才能使得s和t之间不连通。
分析:题意即求最小割,将每个点拆点,点与对应点的边权为去掉该点的花费,原图中所有边的边权赋为无穷大,跑一遍最大流即可。(最大流即最小割)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 6 using namespace std; 7 const int MAXN = 2010; 8 const int MAXM = 1200012; 9 const int INF = 0x3f3f3f3f; 10 struct Edge 11 { 12 int to, next, cap, flow; 13 }edge[MAXM]; 14 int tol; 15 int head[MAXN]; 16 void init() 17 { 18 tol = 2; 19 memset(head, -1, sizeof(head)); 20 } 21 void addedge(int u, int v, int w, int rw=0) 22 { 23 edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; 24 edge[tol].next = head[u]; head[u] = tol++; 25 edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; 26 edge[tol].next = head[v]; head[v] = tol++; 27 } 28 int Q[MAXN]; 29 int dep[MAXN], cur[MAXN], sta[MAXN]; 30 bool bfs(int s, int t, int n) 31 { 32 int front = 0, tail = 0; 33 memset(dep, -1, sizeof(dep[0])*(n+1)); 34 dep[s] = 0; 35 Q[tail++] = s; 36 while(front < tail) 37 { 38 int u = Q[front++]; 39 for(int i = head[u]; i != -1; i = edge[i].next) 40 { 41 int v = edge[i].to; 42 if(edge[i].cap > edge[i].flow && dep[v] == -1) { 43 dep[v] = dep[u] + 1; 44 if(v == t) return true; 45 Q[tail++] = v; 46 } 47 } 48 } 49 return false; 50 } 51 int dinic(int s, int t, int n) { 52 int maxflow = 0; 53 while(bfs(s, t, n)) { 54 for(int i = 0; i < n; i++) cur[i] = head[i]; 55 int u = s, tail = 0; 56 while(cur[s] != -1) 57 { 58 if(u == t) 59 { 60 int tp = INF; 61 for(int i = tail-1; i >= 0; i--) 62 tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow); 63 maxflow+=tp; 64 for(int i = tail-1; i >= 0; i--) { 65 edge[sta[i]].flow+=tp; 66 edge[sta[i]^1].flow-=tp; 67 if(edge[sta[i]].cap-edge[sta[i]].flow==0) 68 tail = i; 69 } 70 u = edge[sta[tail]^1].to; 71 } 72 else 73 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 74 { 75 sta[tail++] = cur[u]; 76 u = edge[cur[u]].to; 77 } 78 else 79 { 80 while(u != s && cur[u] == -1) 81 u = edge[sta[--tail]^1].to; 82 cur[u] = edge[cur[u]].next; 83 } 84 } 85 } 86 return maxflow; 87 } 88 int n,m,s,d; 89 90 int main() 91 { 92 while(~scanf("%d%d",&n,&m)) 93 { 94 init(); 95 scanf("%d%d",&s,&d); 96 int c; 97 for(int i=0;i<n;++i) 98 { 99 scanf("%d",&c); 100 addedge(i,i+n,c); 101 } 102 for(int i=1;i<=m;++i) 103 { 104 int a,b; 105 scanf("%d%d",&a,&b); 106 addedge(a-1+n,b-1,INF); 107 addedge(b-1+n,a-1,INF); 108 } 109 cout<<dinic(s-1,d-1+n,2*n)<<endl; 110 } 111 return 0; 112 }