以前只是A过很简单的最大闭合权像hdu1565之类,完全的最大流模板题。但是都完全不太懂最大闭合权的定义及其用途。
关于最大流的基础知识,大家可以自己网上搜索关键字。有点基础的哥们妹们,推荐看看胡伯涛 《最小割模型在信息学竞赛中的应用》,里面除了很多理论知识以外还有很多不错题集,大家可以练练。
最大闭合权,是最大流一个很经典的应用,关键字:闭合图,最大闭合权。
这种题目表现的模型通常是A-->B-->C,即A事件发生,其后续事件也一定要发生。
如果每个事件发生都有一个效益值的,用最大流算法便可以求出这种效益的最值。
这个题目的另外一个问题是要求删掉的最少点数,乍一看好像很陌生,但是,大家不妨自己举个例子就可以发现这个就是传说中——最简的 、最小割集!
最小割集固然是可能有很多个的,分割的位置便是网络中满流的位置。
这道题求最简的最小割,那就是从源点开始,遍历所有可行边所访问的点集!
帖个水水的代码,希望没有寒碜到大家。WA了n多次,后来发现是计算最大流函数的返回值忘了改成lli。我的钛合金**眼啊!!!!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 typedef long long lli; 6 const int maxn = 5010; 7 const int maxe = 400100; 8 const lli maxf = 1LL<<50; 9 #define smaller(a,b) ((a)<(b)?(a):(b)) 10 struct edge{ 11 int u,v; 12 lli c; 13 edge(int a=0,int b=0,lli d=0){ u=a, v=b, c=d; } 14 }e[maxe]; 15 int head[maxn]; 16 int next[maxe]; 17 int cnt; 18 void add(int u,int v,lli c){ 19 e[cnt] = edge(u,v,c); 20 next[cnt] = head[u], head[u] = cnt++; 21 //printf("cnt = %d,\t%d --> %d with c = %d, next = %d\n",cnt-1,u,v,c,next[cnt-1]); 22 e[cnt] = edge(v,u,0); 23 next[cnt] = head[v], head[v] = cnt++; 24 } 25 //*****// 26 int source,sink,maxdep; 27 int dep[maxn],gap[maxn]; 28 int cur[maxn],trace[maxn],que[maxn],top; 29 void setGD(){ 30 for(int i=0;i<=maxdep;i++) dep[i] = maxdep; 31 dep[sink] = 0; 32 memset(gap,0,sizeof(gap)); 33 gap[dep[sink]] = 1; 34 gap[maxdep] = maxdep; 35 int front,rear,u,v; 36 front = rear = 0; 37 que[rear++] = sink; 38 while(front != rear){ 39 u = que[front++]; 40 if(front >= maxn) front = 0; 41 for(int i=head[u];i!=-1;i=next[i]){ 42 v = e[i].v; 43 if(e[i].c>0 || dep[v] <= dep[u]+1) continue; 44 dep[v] = dep[u]+1; 45 gap[dep[v]]++; 46 que[rear++] = v; 47 if(rear >= maxn) rear = 0; 48 } 49 } 50 } 51 lli maxF(){ 52 setGD(); 53 for(int i=0;i<=maxdep;i++) cur[i] = head[i]; 54 int u=source,i; 55 top = 0; 56 lli flow = 0; 57 while(dep[source] <= maxdep){ 58 if(u == sink){ 59 lli tf = maxf; 60 int ins; 61 for(i=0;i<top;i++){ //找瓶颈边 62 if(tf > e[trace[i]].c){ 63 tf = e[trace[i]].c; 64 ins = i; 65 } 66 } 67 /* 68 for(i=0;i<top;i++) 69 printf("%d -> ",e[trace[i]].u); 70 printf("%d , temp_flow = %d\n",e[trace[top-1]].v,tf); 71 */ 72 for(i=0;i<top;i++){ 73 e[trace[i]].c -= tf; 74 e[trace[i]^1].c += tf; 75 } 76 flow += tf; 77 u = e[trace[ins]].u, top = ins; 78 } 79 if(u != sink && gap[dep[u]-1]==0) break; 80 for(i=cur[u];i!=-1;i=next[i]) 81 if(e[i].c > 0 && dep[u] == dep[e[i].v] + 1) 82 break; 83 if(i != -1) { 84 trace[top++] = i; 85 cur[u] = i; 86 u = e[i].v; 87 } 88 else { 89 int mindep = maxdep; 90 for(i=head[u];i!=-1;i=next[i]){ 91 if(e[i].c > 0 && dep[e[i].v] < mindep) 92 mindep = dep[e[i].v], cur[u] = i; 93 } 94 gap[dep[u]]--; 95 dep[u] = mindep + 1; 96 gap[dep[u]]++; 97 if(u != source) 98 u = e[trace[--top]].u; 99 } 100 } 101 return flow; 102 } 103 //**********************// 104 int visited[maxn]; 105 int value[maxn]; 106 void initial() 107 { 108 cnt = 0; 109 memset(head,-1,sizeof(head)); 110 memset(visited,0,sizeof(visited)); 111 //initial source ,sink and maxdep; 112 } 113 int era; 114 void search(int u){ 115 //cout<<"u = "<<u<<endl; 116 visited[u] = 1; 117 era++; 118 for(int i=head[u];i>=0;i=next[i]) 119 if(!visited[e[i].v] && e[i].c) 120 search(e[i].v); 121 } 122 int main() 123 { 124 int n,m; 125 while(scanf("%d%d",&n,&m) != EOF){ 126 lli sum = 0; 127 int u,v,c; 128 initial(); 129 source=0,sink=n+2,maxdep=sink+2; 130 for(int i=1;i<=n;i++){ 131 scanf("%d",&c); 132 value[i] = c; 133 if(c > 0) add(source,i,c), sum+=c; 134 else if(c < 0) add(i,sink,-c); 135 } 136 for(int i=0;i<m;i++) 137 scanf("%d%d",&u,&v), add(u,v,maxf); 138 lli ret = maxF(); 139 //if(ret >= sum) puts("0 0"); else { 140 era = 0; 141 search(source); 142 cout<<(era-1)<<" "<<(sum-ret)<<endl; 143 //} 144 } 145 return 0; 146 }