网络流之关键边

题目
题意: 给定有向图,求出图中的所有关键边。
思路: 所谓的关键边,即增大这条边的边权之后能增大最大流的流量。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 502;
const int M = 2*(5002+N);
const ll INF = 1e18;
int q[N]; int d[N]; int cur[N];
int h[N],e[M],ne[M];
ll w[M]; //对应边的流量
ll f[M]; //对应边的容量
int idx = 0;
int in[N],out[N];
int st,ed,st2,ed2;
int n,m,k,T;
bool vis[N];
bool l[N],r[N];
void add(int a,int b,ll c)
{
	e[idx] = b,w[idx] = c,f[idx] = c,ne[idx] = h[a],h[a] = idx++;
}
void dfs(int u,int wh)
{
	if(wh==0) l[u] = 1;
	else r[u] = 1;
	vis[u] = 1;
	for(int i=h[u];~i;i=ne[i])
	{
		int j = e[i];
		if(!vis[j]&&w[i^wh]) //对应的正向边不满流.
		{
			dfs(j,wh);
		}
	}
}
bool bfs()
{
	int hh = 0,tt = 0;
	memset(d,-1,sizeof(d));
	d[st] = 0,cur[st] = h[st],q[tt++] = st;
	while(hh!=tt)
	{
		int u = q[hh++];
		for(int i=h[u];~i;i=ne[i])
		{
			int j = e[i];
			if(d[j]==-1&&w[i])
			{
				d[j] = d[u] + 1;
				cur[j] = h[j];
				if(j==ed) return true;
				q[tt++] = j;
			}
		}
	}
	return 0;
}
ll find(int u,ll limit)
{
	if(u==ed) return limit;
	ll flow = 0;
	for(int i=cur[u];~i&&flow<limit;i=ne[i])
	{
	    cur[u] = i;
		int j = e[i];
		if(d[j]==d[u]+1&&w[i])
		{
			ll t = find(j,min(1ll*w[i],limit-flow));
			if(!t) d[j] = -1;
			flow += t; w[i] -= t,w[i^1] += t;
		}
	}
	return flow;
}
ll dinic()
{
	ll ans = 0,flow;
	while(bfs()) while(flow = find(st,INF)) ans += flow;
	return ans;
}
void solve()
{
	memset(h,-1,sizeof(h));
	scanf("%d%d",&n,&m);
	st = 0,ed = n-1;
	while(m--)
	{
		int a,b,c; scanf("%d%d%d",&a,&b,&c);
		add(a,b,c),add(b,a,0);
	}
	ll ans = dinic();
	// cout<<ans<<"??\n";
	ll res = 0;
	memset(vis,false,sizeof(vis));
	dfs(st,0);
	memset(vis,false,sizeof(vis));
	dfs(ed,1);
	for(int i=0;i<idx;i+=2)
	{
		if(w[i]==0)
		{
			int t2 = e[i];
			int t1 = e[i^1];
			if(l[t1]&&r[t2]) res++;
		}
	}
	cout<<res;
}
signed main(void)
{
	solve();
	return 0;
}
/*
3 2 1 3
1 2 1000 2000
2 3 100 200
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值