Time Limit: 2000MS | Memory Limit: 131072K | |
Total Submissions: 5789 | Accepted: 1617 |
Description
Ikki is the king of a small country – Phoenix, Phoenix is so small that there is only one city that is responsible for the production of daily goods, and uses the road network to transport the goods to the capital. Ikki finds that the biggest problem in the country is that transportation speed is too slow.
Since Ikki was an ACM/ICPC contestant before, he realized that this, indeed, is a maximum flow problem. He coded a maximum flow program and found the answer. Not satisfied with the current status of the transportation speed, he wants to increase the transportation ability of the nation. The method is relatively simple, Ikki will reconstruct some roads in this transportation network, to make those roads afford higher capacity in transportation. But unfortunately, the country of Phoenix is not so rich in GDP that there is only enough money to rebuild one road. Ikki wants to find such roads that if reconstructed, the total capacity of transportation will increase.
He thought this problem for a loooong time but cannot get it. So he gave this problem to frkstyc, who put it in this POJ Monthly contest for you to solve. Can you solve it for Ikki?
Input
The input contains exactly one test case.
The first line of the test case contains two integers N, M (N ≤ 500, M ≤ 5,000) which represents the number of cities and roads in the country, Phoenix, respectively.
M lines follow, each line contains three integers a, b, c, which means that there is a road from city a to city b with a transportation capacity of c (0 ≤ a, b < n, c ≤ 100). All the roads are directed.
Cities are numbered from 0 to n − 1, the city which can product goods is numbered 0, and the capital is numbered n − 1.
Output
Sample Input
2 1 0 1 1
Sample Output
1
大致思路:枚举残量网络中当前剩余流量为0的边,看是否能通过在这条边加流可达
sap:32ms
#include<cstdio> #include<cstring> const int N=502; const int M=100002; const int INF=0x7fffffff; int tol,n,m,s,t; int head[N],arc[N],pre[N],dis[N],gap[N]; bool map[N][N],vx[N],vy[N]; struct node { int x,y,f,nxt; }edge[M]; void add(int x,int y,int f) { edge[tol].x=x; edge[tol].y=y; edge[tol].f=f; edge[tol].nxt=head[x]; head[x]=tol++; edge[tol].x=y; edge[tol].y=x; edge[tol].f=0; edge[tol].nxt=head[y]; head[y]=tol++; } void sap() { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); memcpy(arc,head,sizeof(dis)); gap[0]=n; int ans=0,arg=INF,u=pre[s]=s; while(dis[s]<n) { L: for(int &i=arc[u];i!=-1;i=edge[i].nxt) { int v=edge[i].y; if(edge[i].f&&dis[u]==dis[v]+1) { if(arg>edge[i].f)arg=edge[i].f; pre[v]=u; u=v; if(v==t) { ans+=arg; for(u=pre[u];v!=s;v=u,u=pre[u]) { edge[arc[u]].f-=arg; edge[arc[u]^1].f+=arg; } arg=INF; } goto L; } } int min=n; for(int i=head[u];i!=-1;i=edge[i].nxt) { int v=edge[i].y; if(edge[i].f&&min>dis[v]) { arc[u]=i; min=dis[v]; } } if(--gap[dis[u]]==0)break; dis[u]=min+1; gap[dis[u]]++; u=pre[u]; } } void dfs(int x,bool v[]) { v[x]=1; for(int i=head[x];i!=-1;i=edge[i].nxt) { int y=edge[i].y; if(!v[y]&&map[x][y])dfs(y,v); } } void run() { int i; memset(map,0,sizeof(map)); memset(vx,0,sizeof(vx)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].x][edge[i].y]=1; dfs(s,vx); memset(map,0,sizeof(map)); memset(vy,0,sizeof(vy)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].y][edge[i].x]=1; dfs(t,vy); int ans=0; for(i=0;i<tol;i+=2)if(vx[edge[i].x]&&vy[edge[i].y]&&edge[i].f==0)ans++; printf("%d\n",ans); } int main() { int i; while(~scanf("%d%d",&n,&m)) { s=0;t=n-1; memset(head,-1,sizeof(head)); tol=0; int x,y,c; while(m--) { scanf("%d%d%d",&x,&y,&c); add(x,y,c); } sap(); run(); } return 0; }
dinic:47ms#include<cstdio> #include<cstring> const int N=502; const int M=100002; const int INF=0x7fffffff; int tol,n,m,s,t; int head[N],d[N]; bool map[N][N],vx[N],vy[N]; struct node { int x,y,f,nxt; }edge[M]; int min(int a,int b){return a<b?a:b;} void add(int x,int y,int f) { edge[tol].x=x; edge[tol].y=y; edge[tol].f=f; edge[tol].nxt=head[x]; head[x]=tol++; edge[tol].x=y; edge[tol].y=x; edge[tol].f=0; edge[tol].nxt=head[y]; head[y]=tol++; } bool bfs() { int front=0,rear=0,q[N],u,v,i; memset(d,-1,sizeof(d)); d[s]=0; q[rear++]=s; while(front<rear) { u=q[front++]; for(i=head[u];i!=-1;i=edge[i].nxt) { v=edge[i].y; if(edge[i].f&&d[v]==-1) { d[v]=d[u]+1; if(v==t)return 1; q[rear++]=v; } } } return 0; } int dfs(int s,int limit) { if(s==t)return limit; int i,v,tmp,sum=0; for(i=head[s];i!=-1;i=edge[i].nxt) { v=edge[i].y; if(edge[i].f&&d[s]+1==d[v]) { tmp=dfs(v,min(limit-sum,edge[i].f)); edge[i].f-=tmp; edge[i^1].f+=tmp; sum+=tmp; if(limit==sum)return sum; } } if(sum==0)d[s]=-1; return sum; } void dinic(){while(bfs())dfs(s,INF);} void check(int x,bool v[]) { v[x]=1; for(int i=head[x];i!=-1;i=edge[i].nxt) { int y=edge[i].y; if(!v[y]&&map[x][y])check(y,v); } } void run() { int i; memset(map,0,sizeof(map)); memset(vx,0,sizeof(vx)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].x][edge[i].y]=1; check(s,vx); memset(map,0,sizeof(map)); memset(vy,0,sizeof(vy)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].y][edge[i].x]=1; check(t,vy); int ans=0; for(i=0;i<tol;i+=2)if(vx[edge[i].x]&&vy[edge[i].y]&&edge[i].f==0)ans++; printf("%d\n",ans); } int main() { int i; while(~scanf("%d%d",&n,&m)) { s=0;t=n-1; memset(head,-1,sizeof(head)); tol=0; int x,y,c; while(m--) { scanf("%d%d%d",&x,&y,&c); add(x,y,c); } dinic(); run(); } return 0; }
Edmond-Karp:93ms#include<cstdio> #include<cstring> const int N=502; const int M=100002; const int INF=0x7fffffff; int tol,n,m,s,t; int head[N],pre[N],e[N]; bool map[N][N],vx[N],vy[N]; struct node { int x,y,f,nxt; }edge[M]; int min(int a,int b){return a<b?a:b;} void add(int x,int y,int f) { edge[tol].x=x; edge[tol].y=y; edge[tol].f=f; edge[tol].nxt=head[x]; head[x]=tol++; edge[tol].x=y; edge[tol].y=x; edge[tol].f=0; edge[tol].nxt=head[y]; head[y]=tol++; } bool bfs() { int front=0,rear=0,q[N],u,v,i; memset(pre,-1,sizeof(pre)); memset(e,-1,sizeof(e)); q[rear++]=s; while(front<rear) { u=q[front++]; for(i=head[u];i!=-1;i=edge[i].nxt) { v=edge[i].y; if(edge[i].f&&pre[v]==-1) { pre[v]=u; e[v]=i; if(v==t)return 1; q[rear++]=v; } } } return 0; } void augment() { int min=INF,i=t,v; while(i!=s) { if(min>edge[e[i]].f) min=edge[e[i]].f; i=pre[i]; } i=t; while(i!=s) { edge[e[i]].f-=min; edge[e[i]^1].f+=min; i=pre[i]; } } void EK(){while(bfs())augment();} void check(int x,bool v[]) { v[x]=1; for(int i=head[x];i!=-1;i=edge[i].nxt) { int y=edge[i].y; if(!v[y]&&map[x][y])check(y,v); } } void run() { int i; memset(map,0,sizeof(map)); memset(vx,0,sizeof(vx)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].x][edge[i].y]=1; check(s,vx); memset(map,0,sizeof(map)); memset(vy,0,sizeof(vy)); for(i=0;i<tol;i+=2)if(edge[i].f)map[edge[i].y][edge[i].x]=1; check(t,vy); int ans=0; for(i=0;i<tol;i+=2)if(vx[edge[i].x]&&vy[edge[i].y]&&edge[i].f==0)ans++; printf("%d\n",ans); } int main() { int i; while(~scanf("%d%d",&n,&m)) { s=0;t=n-1; memset(head,-1,sizeof(head)); tol=0; int x,y,c; while(m--) { scanf("%d%d%d",&x,&y,&c); add(x,y,c); } EK(); run(); } return 0; }
(原来很暴力的算法,纪念一下)Edmond-Karp:813ms
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=502; const int M=5002; const int INF=0x7fffffff; int head[N],from[M],to[M],nxt[M],cnt; int cap[N][N],pre[N],n,m; void add(int a,int b,int c) { cap[a][b]=c; nxt[cnt]=head[a]; head[a]=cnt++; } bool bfs(int s,int t) { queue<int> Q; memset(pre,-1,sizeof(pre)); Q.push(s);pre[s]=s; while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) { int v=to[i]; if(pre[v]==-1&&cap[u][v]>0) { pre[v]=u; if(v==t) return true; Q.push(v); } } } return false; } void augment(int s,int t) { int min=INF,i=t,v; while(i!=s) { v=pre[i]; if(min>cap[v][i]) min=cap[v][i]; i=v; } i=t; while(i!=s) { v=pre[i]; cap[v][i]-=min; cap[i][v]+=min; i=v; } } void run() { int i; int co=0; for(i=0;i<m;i++) { if(cap[from[i]][to[i]]==0) { cap[from[i]][to[i]]=1; if(bfs(0,n-1))co++; cap[from[i]][to[i]]=0; } } printf("%d\n",co); } int main() { int i,c; while(~scanf("%d%d",&n,&m)){ memset(cap,0,sizeof(cap)); memset(head,-1,sizeof(head)); cnt=0; for(i=0;i<m;i++) { scanf("%d%d%d",&from[i],&to[i],&c); add(from[i],to[i],c); } while(bfs(0,n-1)) augment(0,n-1); run(); } return 0; }