题目链接:http://poj.org/problem?id=3204
思路:显然只有增大那最小割边集上的边才能增加最大流,因此,我们可以先跑一遍最大流,然后对于那些满足条件的边u->v,当且仅当从源点开始沿着正向边能遍历到u,从汇点开始沿着正向边能遍历到v.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 555 8 #define MAXM 55555 9 #define inf 1<<30 10 11 struct Edge{ 12 int v,cap,next; 13 }edge[MAXM]; 14 15 int n,m,NE,NV,vs,vt; 16 int head[MAXN]; 17 18 void Insert(int u,int v,int cap) 19 { 20 edge[NE].v=v; 21 edge[NE].cap=cap; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 25 edge[NE].v=u; 26 edge[NE].cap=0; 27 edge[NE].next=head[v]; 28 head[v]=NE++; 29 } 30 31 int level[MAXN],gap[MAXN]; 32 void bfs(int vt) 33 { 34 memset(level,-1,sizeof(level)); 35 memset(gap,0,sizeof(gap)); 36 level[vt]=0; 37 gap[level[vt]]++; 38 queue<int>que; 39 que.push(vt); 40 while(!que.empty()){ 41 int u=que.front(); 42 que.pop(); 43 for(int i=head[u];i!=-1;i=edge[i].next){ 44 int v=edge[i].v; 45 if(level[v]<0){ 46 level[v]=level[u]+1; 47 gap[level[v]]++; 48 que.push(v); 49 } 50 } 51 } 52 } 53 54 int pre[MAXN],cur[MAXN]; 55 int SAP(int vs,int vt) 56 { 57 bfs(vt); 58 memset(pre,-1,sizeof(pre)); 59 memcpy(cur,head,sizeof(head)); 60 int maxflow=0; 61 int u=pre[vs]=vs,aug=inf; 62 gap[0]=NV; 63 while(level[vs]<NV){ 64 bool flag=false; 65 for(int &i=cur[u];i!=-1;i=edge[i].next){ 66 int v=edge[i].v; 67 if(edge[i].cap>0&&level[u]==level[v]+1){ 68 flag=true; 69 pre[v]=u; 70 u=v; 71 aug=min(aug,edge[i].cap); 72 if(v==vt){ 73 maxflow+=aug; 74 for(u=pre[v];v!=vs;v=u,u=pre[u]){ 75 edge[cur[u]].cap-=aug; 76 edge[cur[u]^1].cap+=aug; 77 } 78 aug=inf; 79 } 80 break; 81 } 82 } 83 if(flag)continue; 84 int minlevel=NV; 85 for(int i=head[u];i!=-1;i=edge[i].next){ 86 int v=edge[i].v; 87 if(edge[i].cap>0&&level[v]<minlevel){ 88 minlevel=level[v]; 89 cur[u]=i; 90 } 91 } 92 if(--gap[level[u]]==0)break; 93 level[u]=minlevel+1; 94 gap[level[u]]++; 95 u=pre[u]; 96 } 97 return maxflow; 98 } 99 100 int vis[MAXN]; 101 void dfs1(int u) 102 { 103 vis[u]=1; 104 for(int i=head[u];i!=-1;i=edge[i].next){ 105 int v=edge[i].v,cap=edge[i].cap; 106 if(cap>0&&!vis[v])dfs1(v); 107 } 108 } 109 110 void dfs2(int u) 111 { 112 vis[u]=2; 113 for(int i=head[u];i!=-1;i=edge[i].next){ 114 int v=edge[i].v,cap=edge[i^1].cap;//注意是正向边容量 115 if(cap>0&&!vis[v])dfs2(v); 116 } 117 } 118 119 int main() 120 { 121 int u,v,w,ans; 122 while(~scanf("%d%d",&n,&m)){ 123 NE=0; 124 memset(head,-1,sizeof(head)); 125 vs=0,vt=n-1,NV=n; 126 for(int i=1;i<=m;i++){ 127 scanf("%d%d%d",&u,&v,&w); 128 Insert(u,v,w); 129 } 130 SAP(vs,vt); 131 ans=0; 132 memset(vis,0,sizeof(vis)); 133 dfs1(0); 134 dfs2(n-1); 135 for(int i=0;i<NE;i+=2){ 136 if(vis[edge[i].v]==2&&vis[edge[i^1].v]==1)ans++; 137 } 138 printf("%d ",ans); 139 } 140 return 0; 141 }