题目:对于一个有向图,提高一条边的容量,可能可以增加该图的最大流。对给定的图,问存在多少条这样的边。
解法:先求最大流,把边填充好,得到残余图。在残余图中,从s出发DFS,把所有能到达的点标记。同样从t出发DFS,把所有能到达的点标记,不过要注意这里边是反向的。最后枚举边,如果边存在、边是满流并且边的两端分别标记了s和t,那么这条边满足要求。
#include <iostream>
using namespace std;
const int maxN=505;
const int maxC=105;
int map[maxN][maxN],flow[maxN][maxN],pre[maxN],minFlow[maxN],belong[maxN];
int MaxFlow(int N,int s, int t)
{
int maxFlow=0;
memset(flow,0,sizeof(flow));
int myQueue[maxN];
while(1)
{
int l=0,r=0;
myQueue[r++]=s;
memset(pre,-1,sizeof(pre));
pre[s]=-2;
minFlow[s]=maxC;
while(l<r)
{
int now=myQueue[l++];
for(int i=0;i<N;i++)
{
if(flow[now][i]<map[now][i]&&pre[i]==-1)
{
myQueue[r++]=i;
minFlow[i]=min(minFlow[now],map[now][i]-flow[now][i]);
pre[i]=now;
}
}
if(pre[t]!=-1)
{
int end=t;
while(pre[end]!=-2)
{
flow[pre[end]][end]+=minFlow[t];
flow[end][pre[end]]=-flow[pre[end]][end];
end=pre[end];
}
maxFlow+=minFlow[t];
break;
}
}
if(pre[t]==-1)
return maxFlow;
}
}
void NodesConnectedToS(int N,int s,int record[maxN])
{
record[s]=s;
bool visited[maxN];
memset(visited,0,sizeof(visited));
int myStack[maxN],index=0;
myStack[index++]=s;
visited[s]=true;
while(index--!=0)
{
int now=myStack[index];
for(int i=0;i<N;i++)
{
if(map[now][i]>0&&flow[now][i]<map[now][i]&&!visited[i])
{
record[i]=s;
myStack[index++]=i;
visited[i]=true;
}
}
}
}
void NodesConnectedToT(int N,int t,int record[maxN])
{
record[t]=t;
bool visited[maxN];
memset(visited,0,sizeof(visited));
int myStack[maxN],index=0;
myStack[index++]=t;
visited[t]=true;
while(index--!=0)
{
int now=myStack[index];
for(int i=0;i<N;i++)
{
if(map[i][now]>0&&flow[i][now]<map[i][now]&&!visited[i])
{
record[i]=t;
myStack[index++]=i;
visited[i]=true;
}
}
}
}
int main()
{
//freopen("f:\\in.txt","r",stdin);
memset(map,0,sizeof(map));
int n,m;
scanf("%d%d",&n,&m);
int a,b,c;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[a][b]=c;
}
MaxFlow(n,0,n-1);
int ans=0;
memset(belong,-1,sizeof(belong));
NodesConnectedToS(n,0,belong);
NodesConnectedToT(n,n-1,belong);
for(int i=0;i<n;i++)
{
if(belong[i]==-1) continue;
for(int j=0;j<n;j++)
{
if(belong[j]==-1) continue;
if(map[i][j]>0&&map[i][j]==flow[i][j]&&belong[i]!=belong[j]) ans++;
}
}
printf("%d\n",ans);
}