【题意】
【分析】
【建图】
留着有空再写
【Mark】
数据较大,n<=20000。使用dinic的递归写法跑了7s+,非递归TLE.sap跑了2s+。
谁说非递归效率高?


1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int N=20100; 9 const int M=200200; 10 const int inf=100000000; 11 12 struct node 13 { 14 int v,f; 15 int next; 16 } edge[8*M]; 17 int head[N],num; 18 int n,m; 19 int s,t,NN; 20 21 void init() 22 { 23 memset(head,-1,sizeof(head)); 24 num=0; 25 } 26 27 void addege(int u,int v,int f) 28 { 29 edge[num].v=v; 30 edge[num].f=f; 31 edge[num].next=head[u]; 32 head[u]=num++; 33 edge[num].v=u; 34 edge[num].f=0; 35 edge[num].next=head[v]; 36 head[v]=num++; 37 } 38 39 int sap() 40 { 41 int pre[N],cur[N],dis[N],gap[N]; 42 int flow=0,aug=inf,u; 43 bool flag; 44 int i; 45 for(i=1; i<=NN; i++) 46 { 47 cur[i]=head[i]; 48 gap[i]=dis[i]=0; 49 } 50 gap[s]=NN; 51 u=pre[s]=s; 52 while(dis[s]<NN) 53 { 54 flag=0; 55 for(int &j=cur[u]; j!=-1; j=edge[j].next) 56 { 57 int v=edge[j].v; 58 if(edge[j].f>0 && dis[u]==dis[v]+1) 59 { 60 flag=1; 61 if(edge[j].f<aug) aug=edge[j].f; 62 pre[v]=u; 63 u=v; 64 if(u==t) 65 { 66 flow+=aug; 67 while(u!=s) 68 { 69 u=pre[u]; 70 edge[cur[u]].f-=aug; 71 edge[cur[u]^1].f+=aug; 72 } 73 aug=inf; 74 } 75 break; 76 } 77 } 78 if(flag) continue; 79 int mindis=NN; 80 for(int j=head[u]; j!=-1; j=edge[j].next) 81 { 82 int v=edge[j].v; 83 if(edge[j].f>0 && dis[v]<mindis) 84 { 85 mindis=dis[v]; 86 cur[u]=j; 87 } 88 } 89 if((--gap[dis[u]])==0) break; 90 gap[dis[u]=mindis+1]++; 91 u=pre[u]; 92 } 93 return flow; 94 } 95 96 int main() 97 { 98 while (scanf("%d%d",&n,&m)==2) 99 { 100 int i,j; 101 int a,b,w; 102 s=0; 103 t=n+1; 104 NN=n+2; 105 init(); 106 for(i=1; i<=n; i++) 107 { 108 scanf("%d%d",&a,&b); 109 addege(s,i,a); 110 addege(i,t,b); 111 } 112 for(i=1; i<=m; i++) 113 { 114 scanf("%d%d%d",&a,&b,&w); 115 addege(a,b,w); 116 addege(b,a,w); 117 } 118 printf("%d\n",sap()); 119 } 120 return 0; 121 }


1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 6 using namespace std; 7 8 #define INF 1e8 9 #define MAX_VECT 20005 10 #define MAX_EDGE 2200000 11 12 /************************************************************************/ 13 /* Name: dinic 14 /* Description: Find the max flow of the network from start to 15 end point 16 /* Variable Description: to[] - end point of the current edge 17 next[] - the next edge which also comes from 18 the same point as current edge 19 cap[] - the capability of the current edge 20 v[] - the first edge index which comes from the 21 the current point 22 d[] - the layer number of current point 23 /************************************************************************/ 24 25 26 int to[MAX_EDGE], next[MAX_EDGE], cap[MAX_EDGE], tot; 27 int v[MAX_VECT], d[MAX_VECT], queue[MAX_VECT], n; 28 int S, T; 29 inline void single_insert(int _u, int _v, int var) 30 { 31 to[tot] = _v; 32 cap[tot] = var; 33 next[tot] = v[_u]; 34 v[_u] = tot++; 35 } 36 37 void insert(int from, int to, int cap) 38 { 39 single_insert(from, to, cap); 40 single_insert(to, from, 0); 41 } 42 43 bool bfs_initial() 44 { 45 memset(d, -1, sizeof(d)); 46 int bg, ed, x, y; 47 bg = ed = d[S] = 0; 48 queue[ed++] = S; 49 while (bg < ed) 50 { 51 x = queue[bg++]; 52 for (int i = v[x]; i+1; i = next[i]) 53 { 54 y = to[i]; 55 if (cap[i] && d[y] == -1) 56 { 57 d[y] = d[x] + 1; 58 if (y == T) return true; 59 queue[ed++] = y; 60 } 61 } 62 } 63 return false; 64 } 65 66 int Find(int x, int low = INF) 67 { 68 if (x == T) return low; 69 int ret, y, ans = 0; 70 for (int i = v[x]; (i+1) && low; i = next[i]) 71 { 72 y = to[i]; 73 if (cap[i] && d[y] == d[x] + 1 && (ret = Find(y, min(low, cap[i])))) 74 { 75 cap[i] -= ret; 76 cap[i^1] += ret; 77 low -= ret; 78 ans += ret; 79 } 80 } 81 return ans; 82 } 83 int dinic() 84 { 85 int ans = 0; 86 while (bfs_initial()) 87 ans += Find(S); 88 return ans; 89 } 90 91 92 int dinicc() 93 { 94 int ans = 0; 95 while(bfs_initial()) 96 { 97 int edge, x, y, back, iter = 1; 98 while(iter) 99 { 100 x = (iter == 1) ? S : to[queue[iter - 1]]; 101 if (x == T) 102 { 103 int minE, minCap = INF; 104 for (int i = 1; i < iter; i++) 105 { 106 edge = queue[i]; 107 if (cap[edge] < minCap) 108 { 109 minCap = cap[edge]; 110 back = i; 111 } 112 } 113 for (int i = 1; i < iter; i++) 114 { 115 edge = queue[i]; 116 cap[edge] -= minCap; 117 cap[edge ^ 1] += minCap; 118 } 119 ans += minCap; 120 iter = back; 121 } 122 else 123 { 124 for (edge = v[x]; edge + 1; edge = next[edge]) 125 { 126 y = to[edge]; 127 if (cap[edge] && d[y] == d[x] + 1) 128 break; 129 } 130 if (edge+1) 131 queue[iter++] = edge; 132 else 133 { 134 d[x] = -1; 135 iter--; 136 } 137 } 138 } 139 } 140 return ans; 141 } 142 143 int m; 144 145 int main() 146 { 147 while (scanf("%d%d",&n,&m)==2) 148 { 149 memset(v,-1,sizeof(v)); 150 tot = 0; 151 S = 0; 152 T = n+1; 153 for (int i=1;i<=n;i++) 154 { 155 int a,b; 156 scanf("%d%d",&a,&b); 157 insert(S,i,a); 158 insert(i,T,b); 159 } 160 for (int i=1;i<=m;i++) 161 { 162 int u,v,w; 163 scanf("%d%d%d",&u,&v,&w); 164 insert(u,v,w); 165 insert(v,u,w); 166 } 167 n++; 168 int ans = dinic(); 169 printf("%d\n",ans); 170 } 171 return 0; 172 }
本文对比了两种最大流算法:SAP和Dinic在POJ3469问题上的性能表现。通过具体实现和测试,发现对于大规模数据集(n<=20000),SAP算法在非递归效率上优于Dinic算法的递归写法,但Dinic的非递归版本也展现出了良好的性能。
549

被折叠的 条评论
为什么被折叠?



