POJ 3204 Ikki's Story I - Road Reconstruction(最大流-Dinic)
2015-08-13 10:57
417 查看
Description
在一个网络里面,问增大哪条边的容量可以使整个网络的流量增大,输出这种边个数
Input
第一行两个整数N和M分别表示点数和边数,之后M行每行三个整数a,b,c表示a到b有一条容量为c的边
Output
输出满足条件的边的个数
Sample Input
2 1
0 1 1
Sample Output
1
Solution
首先对整个网络求最大流得到残余网络,对参与网络中正向弧剩余容量为0的边标记vis,对剩余容量不为0的边建立两张方向相反的新图,对正向新图一遍dfs将所有源点能到达的点标记vis1,对反向图一遍dfs将所有汇点能到达的点标记vis2,最后再枚举原图中所有的边,如果该边被表示vis,且起点被表示vis1,终点被标记vis2的话,则表明如果增肌这条边的容量则可以增大原网络的最大流,统计这种边的个数即为答案
Code
在一个网络里面,问增大哪条边的容量可以使整个网络的流量增大,输出这种边个数
Input
第一行两个整数N和M分别表示点数和边数,之后M行每行三个整数a,b,c表示a到b有一条容量为c的边
Output
输出满足条件的边的个数
Sample Input
2 1
0 1 1
Sample Output
1
Solution
首先对整个网络求最大流得到残余网络,对参与网络中正向弧剩余容量为0的边标记vis,对剩余容量不为0的边建立两张方向相反的新图,对正向新图一遍dfs将所有源点能到达的点标记vis1,对反向图一遍dfs将所有汇点能到达的点标记vis2,最后再枚举原图中所有的边,如果该边被表示vis,且起点被表示vis1,终点被标记vis2的话,则表明如果增肌这条边的容量则可以增大原网络的最大流,统计这种边的个数即为答案
Code
#include<cstdio> #include<iostream> #include<cstring> #include<queue> using namespace std; #define maxn 555 #define maxm 11111 #define INF 0x3f3f3f3f int head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no; struct point { int u,v,flow,next; point(){}; point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){}; }p[maxm]; void add(int x,int y,int z) { p[no]=point(x,y,head[x],z); head[x]=no++; p[no]=point(y,x,head[y],0); head[y]=no++; } void init() { memset(head,-1,sizeof(head)); no=0; } bool bfs() { int i,x,y; queue<int>q; memset(d,-1,sizeof(d)); d[s]=0; q.push(s); while(!q.empty()) { x=q.front(); q.pop(); for(i=head[x];i!=-1;i=p[i].next) { if(p[i].flow&& d[y = p[i].v]<0) { d[y]=d[x]+1; if(y==e) return true; q.push(y); } } } return false; } int dinic() { int i,loc,top,x=s,nowflow,maxflow=0; while(bfs()){ for(i=s;i<=e;i++) cur[i]=head[i]; top=0; while(true) { if(x==e) { nowflow=INF; for(i=0;i<top;i++) { if(nowflow>p[st[i]].flow) { nowflow=p[st[i]].flow; loc=i; } } for(i=0;i<top;i++) { p[st[i]].flow-=nowflow; p[st[i]^1].flow+=nowflow; } maxflow+=nowflow; top=loc; x=p[st[top]].u; } for(i=cur[x];i!=-1;i=p[i].next) if(p[i].flow&&d[p[i].v]==d[x]+1) break; cur[x]=i; if(i!=-1) { st[top++]=i; x=p[i].v; } else { if(!top) break; d[x]=-1; x=p[st[--top]].u; } } } return maxflow; } int N,M; struct node { int to; int next; }; node edge1[maxm],edge2[maxm]; int head1[maxn],head2[maxn]; int tol1,tol2; bool vis[maxm],vis1[maxm],vis2[maxm]; void init1() { tol1=tol2=0; memset(vis,false,sizeof(vis)); memset(vis1,false,sizeof(vis1)); memset(vis2,false,sizeof(vis2)); memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); } void add1(int u,int v) { edge1[tol1].to=v; edge1[tol1].next=head1[u]; head1[u]=tol1++; } void add2(int u,int v) { edge2[tol2].to=v; edge2[tol2].next=head2[u]; head2[u]=tol2++; } void dfs1(int u) { vis1[u]=true; for(int i=head1[u];i!=-1;i=edge1[i].next) { int v=edge1[i].to; if(!vis1[v]) dfs1(v); } } void dfs2(int u) { vis2[u]=true; for(int i=head2[u];i!=-1;i=edge2[i].next) { int v=edge2[i].to; if(!vis2[v]) dfs2(v); } } int main() { scanf("%d%d",&N,&M); init();//初始化 s=0;//源点为0 e=N-1;//汇点为N-1 for(int i=0;i<M;i++) { int u,v,f; scanf("%d%d%d",&u,&v,&f); add(u,v,f);//建边 } dinic();//求最大流得到残余网络 init1();//初始化 for(int i=0;i<M;i++) { if(p[2*i].flow==0)//对残余网络中正向弧容量为0的边标记 vis[i]=true; else//对残余网络中正向弧容量不为0的边建立两张方向相反的新图 { add1(p[2*i].u,p[2*i].v); add2(p[2*i].v,p[2*i].u); } } dfs1(s);//对第一张新图中所有源点可达的点标记 dfs2(e);//对第二张新图中所有汇点可达的点标记 int ans=0; for(int i=0;i<M;i++)//统计满足条件的边的数量 if(vis[i]&&vis1[p[2*i].u]&&vis2[p[2*i].v]) ans++; printf("%d\n",ans); return 0; }
相关文章推荐
- 九度 Online Judge 算法 刷题 题目1049:字符串去特定字符
- 使用DraweLayout实现史上最简洁的侧滑菜单
- Python模块安装方法
- android 开源组件合集-UI篇(2014-08-25更新)
- eclipse配置maven
- 百度地图SDK
- Duanxx的C++学习: 使用类没有被定义 原因及解决方法
- 【Ex2013】【IIS-W3SVC-WP 2280】 重装ex后报错Owa、EMS无法访问
- kernel: segfault at *** rip *** rsp *** error
- QString类
- 系统设计的典型分层和涉及的知识点
- 感觉最近老被人叉
- Process 重定向处理
- POJ 2527 Polynomial Remains 多项式运算
- Image$$
- Spring配置datasource三种方式
- hadoop 视频网站
- 安全基础教育第二季第1集:屡战屡败的找回密码
- 待解决的问题
- 排序算法系列——希尔排序