题目
n个外籍飞行员和m个皇家飞行员分别能互相配合,给出能互相配合的飞行员序号对,每个飞行员只能配一次对,求最大对数
题解
最大匹配也可以做,但是练习网络流才是第一要务。。。
建图很简单,设源点s和汇点t,在每个外籍飞行员和s之间连边,每个皇家飞行员和t之间连边,然后跑最大流就可以了,这里用的是dinic
我改了许久,wa,te,re都试过,最后发现,数组开小了!!!
代码
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct edge{
int y,c,ne;
}e[10000];
int n,m,ls[105],s,t,cnt,cur[105],dis[105],a[105][105];
queue<int> que;
void addedge(int u,int v,int c)
{
a[u][v]=1;
e[++cnt].y=v;e[cnt].c=c;e[cnt].ne=ls[u];ls[u]=cnt;
e[++cnt].y=u;e[cnt].c=0;e[cnt].ne=ls[v];ls[v]=cnt;
}
bool bfs()
{
for (int i=0;i<=n+1;i++) dis[i]=0;
while (!que.empty()) que.pop();
dis[s]=1;que.push(s);
while (!que.empty())
{
int u=que.front();que.pop();
for (int i=ls[u];i;i=e[i].ne)
if (e[i].c&&!dis[e[i].y])
{
dis[e[i].y]=dis[u]+1;
if (e[i].y==t) return(true);
que.push(e[i].y);
}
}
return(false);
}
int dfs(int x,int maxf)
{
if (x==t||!maxf) return(maxf);
int ret=0;
for (int &i=cur[x];i;i=e[i].ne)
if (e[i].c&&(dis[x]+1==dis[e[i].y]))
{
int f=dfs(e[i].y,min(e[i].c,maxf-ret));
e[i].c-=f;
e[i^1].c+=f;
ret+=f;
if (maxf==ret) break;
}
return(ret);
}
int dinic(int t)
{
int ans=0;
s=0;
while (bfs())
{
for (int i=0;i<=n+1;i++) cur[i]=ls[i];
ans+=dfs(s,1000000000);
}
return(ans);
}
void init()
{
int i,j;
cnt=1;
for (int i=1;i<=m;i++)
{
addedge(0,i,1);
a[0][i]=1;
}
for (int i=m+1;i<=n;i++)
{
addedge(i,n+1,1);
a[i][n+1]=1;
}
scanf("%d%d",&i,&j);
while ((i!=-1)&&(j!=-1))
{
if (!a[i][j]) addedge(i,j,1);
scanf("%d%d",&i,&j);
}
}
int main()
{
scanf("%d%d",&m,&n);
init();
s=0;t=n+1;
printf("%d",dinic(t));
}