网络流突击

发布时间 2023-03-27 16:01:05作者: yyx525jia

之前一直都没写(悲
今天下午突击一下网络流24题,看看能写多少题

  1. P2756 飞行员配对方案问题

就是二分图最大匹配求方案数,网络流似乎比匈牙利快?不过空间要大不少

点击查看代码
#include<bits/stdc++.h>
#define for1(i,a,b) for(register ll i = a;i <= b;i ++)
#define ll long long
using namespace std;
const ll maxn = 5e5 + 5;
const ll inf = 1e9 + 7;	
struct node
{
	ll nex;
	ll from;
	ll to;
	ll w;
	ll tag;
}a[maxn<<2];
ll hd[maxn],cnt = 1,ra[maxn];
ll w[maxn] , vis[maxn],n,m,s,t;
ll ans,e;
void ru(ll x , ll y, ll z,ll xx)
{
	a[++cnt].to = y;
	a[cnt].w = z;
	a[cnt].from = x;
	a[cnt].tag = xx;
	a[cnt].nex = hd[x];
	hd[x] = cnt;
	return ;
}

bool bfs()
{
	queue<ll>dl;
	memset(vis,0,sizeof(vis));
	dl.push(s);
	vis[s] = 1;
	while(!dl.empty())
	{
		ll x = dl.front();
		dl.pop();
		ra[x] = hd[x];
		for(ll i = hd[x];i;i = a[i].nex)
		{
			ll v = a[i].to;
			if(vis[v] == 0 && a[i].w)
			{
				vis[v] = vis[x] + 1;
				dl.push(v);
			}
		}
	}
	return vis[t] != 0;
}

ll dfs(ll now, ll can)
{
	if(now == t) return can;
	ll ji = can;
	for(ll i = ra[now];i;i = a[i].nex)
	{
		ll v = a[i].to;
		ra[now] = i;
		if(vis[v] == vis[now] + 1 && a[i].w)
		{
			ll real = min(a[i].w,ji);
			ll ji2 = dfs(v,real);
			a[i].w-= ji2,a[i ^ 1].w += ji2;
			ji -= ji2;
			if(!ji) break;
		}
	}
	return can - ji;
}
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(nullptr);
	cin >> n >> m;
	s = 0,t = n + m + 1;
	for1(i,1,n)
	{
		ru(0,i,1,0);
		ru(i,0,0,0);
	}
	for1(i,1,m)
	{
		ru(i + n , n + m + 1, 1,0);
		ru(n + m + 1, n + i, 0,0);
	}
	
	ll x,y,z;
	while(1)
	{
		cin >> x >> y;
		if(x == -1 && y == -1) break;
		ru(x,y,1,1);
		ru(y,x,0,0);
	}
	while(bfs())
	{
		ans += dfs(s,inf);
	}
	cout << ans << '\n';
	
	for1(i,1,cnt)
		if(a[i].tag == 1 && a[i].w == 0)
			cout << a[i].from << ' ' << a[i].to << '\n';
    return 0;
}