poj 3204 Ikki's Story I - Road Reconstruction(最大流,增广路)
来源:互联网 发布:灰鸽子软件下载 编辑:程序博客网 时间:2024/06/06 03:44
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 10 1 1
Sample Output
1
Source
题意:给出一个有向图,找这样一种边的个数,就是增加该边的容量,可以使得最大流变大。
题解:有两种做法:
1.先跑一遍最大流,得到残流图,然后枚举每一条每一条边,若该条边是要求的边,首先他应该是满流边,即残流为0,然后可以将这条边残流加1,再用bfs判能否找到增广路,如果可以,那么就是要求的边。
2.第二种方法基于这样一个事实,如果一条边是满流边,而且这条边的两个端点都能分别找到到起点和终点的非满流路径,那么这条边是关键边,即为所求。所以先跑一遍最大流,得到残流图, 然后分别从起点和终点沿着非满流边进行bfs,看每个点能否到达起点或终点,然后枚举每一条边,首先要求这条边是满流边,然后边的起点要能到达起点,边的终点要能到达终点,如果可以,那么这条边就是所求的边。
方法1代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>using namespace std;const int MAXN=550;//点数的最大值const int MAXM=5500*2;//边数的最大值const int INF=0x3f3f3f3f;struct Node{ int from,to,next; int cap,before;}edge[MAXM];int tol;int dep[MAXN];//dep为点的层次int head[MAXN];void init(){ tol=0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int w)//第一条边下标必须为偶数{ edge[tol].from=u; edge[tol].to=v; edge[tol].cap=w; edge[tol].before=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].from=v; edge[tol].to=u; edge[tol].cap=0; edge[tol].before=0; edge[tol].next=head[v]; head[v]=tol++;}int BFS(int start,int end){ int que[MAXN]; int front,rear; front=rear=0; memset(dep,-1,sizeof(dep)); que[rear++]=start; dep[start]=0; while(front!=rear) { int u=que[front++]; if(front==MAXN)front=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(edge[i].cap>0&&dep[v]==-1) { dep[v]=dep[u]+1; que[rear++]=v; if(rear>=MAXN)rear=0; if(v==end)return 1; } } } return 0;}int dinic(int start,int end){ int res=0; int top; int stack[MAXN];//stack为栈,存储当前增广路 int cur[MAXN];//存储当前点的后继 while(BFS(start,end)) { memcpy(cur,head,sizeof(head)); int u=start; top=0; while(1) { if(u==end) { int min=INF; int loc; for(int i=0;i<top;i++) if(min>edge[stack[i]].cap) { min=edge[stack[i]].cap; loc=i; } for(int i=0;i<top;i++) { edge[stack[i]].cap-=min; edge[stack[i]^1].cap+=min; } res+=min; top=loc; u=edge[stack[top]].from; } for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next) if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to]) break; if(cur[u]!=-1) { stack[top++]=cur[u]; u=edge[cur[u]].to; } else { if(top==0)break; dep[u]=-1; u=edge[stack[--top]].from; } } } return res;}int main(){int n,m;while(~scanf("%d%d",&n,&m)){init();while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);u++,v++;addedge(u,v,w);}dinic(1,n);int ans=0;for(int u=1;u<=n;u++){for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap==0&&edge[i].before){edge[i].cap+=1;if(BFS(1,n)) ans++;edge[i].cap-=1;}}}printf("%d\n",ans);}return 0;}
至于第二种解法,我至今还没ac。。。附上一个ac代码吧。
AC代码
- poj 3204 Ikki's Story I - Road Reconstruction(最大流,增广路)
- 【POJ】3204 Ikki's Story I - Road Reconstruction 最大流
- poj 3204 Ikki's Story I - Road Reconstruction 最大流
- poj 3204 Ikki's Story I - Road Reconstruction(最大流割边)
- poj 3204 Ikki's Story I - Road Reconstruction (最大流的应用)
- POJ 3204 Ikki's Story I - Road Reconstruction 最大流关键边
- POJ 3204 Ikki's Story I - Road Reconstruction(最大流)
- POJ 3204 Ikki's Story I - Road Reconstruction(最大流-Dinic)
- Poj 3204 Ikki's Story I - Road Reconstruction【最大流Dinic+可行方案边数统计】
- POJ3204 Ikki's Story I - Road Reconstruction [最大流]
- POJ 3204 Ikki's Story I - Road Reconstruction
- poj 3204 Ikki's Story I - Road Reconstruction
- POJ 3204 Ikki's Story I - Road Reconstruction (求割边)
- poj 3204 Ikki's Story I - Road Reconstruction
- POJ-3204-Ikki's Story I - Road Reconstruction
- 【POJ 3204】Ikki's Story I - Road Reconstruction
- POJ 3204 Ikki's Story I - Road Reconstruction 残余网络
- poj 3204 Ikki's Story I - Road Reconstruction(最大流求割边)
- Mysql 时间 '0000-00-00'异常解决
- swarm工作原理
- springmvc resource使用和原理
- Android nice在进程与线程调度中的作用
- 最长公共子序列
- poj 3204 Ikki's Story I - Road Reconstruction(最大流,增广路)
- <hadoop学习历程>--笔记心得8-总结
- velocity把字符串当做模板
- oracle exp命令中的full参数
- matlab calibration toolbox -- matlab标定工具的使用方法--去畸变和双目校正
- [js] ES5
- gallery
- java内存泄漏
- Android 可上下拖拽LinearLayout