POJ

来源:互联网 发布:淘宝推广佣金 编辑:程序博客网 时间:2024/06/08 17:00

传送门:POJ3204

题意:给定一个流网络,找到扩充其容量就能使最大流的流量增加的边,并统计有几条。

思路:根据最大流性质,很容易知道只有最大流中的满流边才有可能成为满足题意的边,因为非满流边你再扩充它它也不可能满流,假设满流边为(u,v),还要满足s到u的存在非满流路径,v到t存在非满流路径才能使得(u,v)成为满足题意的边。所谓非满流路径就是指存在这样一条路径,路径上的边都是非满流的。

我们具体的做法就是跑完最大流以后从源点dfs一次,从汇点dfs一次,当然都是按照非满流边走,将能到达的点分别标记出来,然后再枚举边,看看边是否满流并且两端都被标记过。

代码:

//ISAP int#include <iostream>#include <cstdio>#include <cstring>#include <queue>#define ll long long#define MAXN 505#define inf 0x3f3f3f3fusing namespace std;int n;//实际建图点数(最好比图中总点数大一点)struct Edge{int v,next;int cap,flow;}edge[MAXN*100];int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];int vis1[MAXN],vis2[MAXN];int cnt=0;//实际存储总边数 void init(){cnt=0;memset(pre,-1,sizeof(pre)); }void add(int u,int v,int w,int rw=0)//加边 有向图三个参数,无向图四个 {edge[cnt].v=v;edge[cnt].cap=w;edge[cnt].flow=0;edge[cnt].next=pre[u];pre[u]=cnt++;edge[cnt].v=u;edge[cnt].cap=rw;edge[cnt].flow=0;edge[cnt].next=pre[v];pre[v]=cnt++;}bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长 {memset(dep,-1,sizeof(dep));memset(gap,0,sizeof(gap));gap[0]=1;dep[t]=0;queue<int>q;while(!q.empty())q.pop();q.push(t);//从汇点开始反向建层次图 while(!q.empty()){int u=q.front();q.pop();for(int i=pre[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量{dep[v]=dep[u]+1;gap[dep[v]]++;q.push(v);//if(v==s)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定 //break;}}}return dep[s]!=-1; }int isap(int s,int t){bfs(s,t);memcpy(cur,pre,sizeof(pre));int u=s;path[u]=-1;int ans=0;while(dep[s]<n)//迭代寻找增广路 {if(u==t){int f=inf;for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路 f=min(f,edge[i].cap-edge[i].flow);for(int i=path[u];i!=-1;i=path[edge[i^1].v]){edge[i].flow+=f;edge[i^1].flow-=f;}ans+=f;u=s;continue;}bool flag=false;int v;for(int i=cur[u];i!=-1;i=edge[i].next){v=edge[i].v;if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow){cur[u]=path[v]=i;//当前弧优化 flag=true;break;}}if(flag){u=v;continue;}int x=n;if(!(--gap[dep[u]]))return ans;//gap优化 for(int i=pre[u];i!=-1;i=edge[i].next){if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x){x=dep[edge[i].v];cur[u]=i;//常数优化 }}dep[u]=x+1;gap[dep[u]]++;if(u!=s)//当前点没有增广路则后退一个点 u=edge[path[u]^1].v; }  return ans;}void dfs1(int u){for(int i=pre[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(!vis1[v]&&edge[i].cap>edge[i].flow){vis1[v]=1;dfs1(v);}}}void dfs2(int u){for(int i=pre[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(!vis2[v]&&edge[i^1].cap>edge[i^1].flow){vis2[v]=1;dfs2(v);}}}int main(){int N,M,u,v,w;init();cin>>N>>M;while(M--){scanf("%d%d%d",&u,&v,&w);add(u,v,w);}n=N;isap(0,n-1);vis1[0]=vis2[n-1]=1;dfs1(0);dfs2(n-1);int ans=0;for(int i=0;i<cnt;i+=2){if(vis1[edge[i^1].v]&&vis2[edge[i].v]&&edge[i].cap==edge[i].flow)ans++;}cout<<ans<<endl;}


原创粉丝点击