之前一直都没写(悲
今天下午突击一下网络流24题,看看能写多少题
就是二分图最大匹配求方案数,网络流似乎比匈牙利快?不过空间要大不少
点击查看代码
#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;
}