【题目描述】
国际学生夏令营在北京举行,经过一段时间的活动与交流,同学们逐渐相互了解。组委会决定举行一项派对表演活动,每对由一名中国学生与外国学生组成,要求每对的2位同学在表演技能和语言上能互相配合。在众多的同学中,每一位外国同学都可以与其他若干个中国同学很好地配合。如何选择派对,使得能选出最多的派对。
编程任务:对于给定的外国同学与中国同学的配合情况,编程找出一个最佳派对方案,使得能选出最多的派对。
【输入格式】
第1行的2个数是n和e。n是中国同学(n<=1000);e是同学们的配合数。
接下来e行中,每行有2个正整数i和j,表示外国同学i可以和中国同学j配合。
【输出格式】
将求得的最多的派对数目M输出, 如果所求的最佳派对方案不存在,则在输出'NO SOLUTION'。
【样例输入】 【样例输出】
5 10 51 2
1 3
1 4
1 5
2 3
2 4
2 5
3 1
4 2
5 3
裸的网络流,数据范围是1000,还是用Dinic比较保险,注意一下流量为0时,特判输出即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,cnt=-1,h[2005],ans,head,tail,q[100005],pre[2005],s,t;
struct que
{
int to,next,d;
}w[200005];
void add(int x,int y,int z)
{
cnt++;
w[cnt].to=y;
w[cnt].d=z;
w[cnt].next=h[x];
h[x]=cnt;
}
bool bfs()
{
memset(pre,0,sizeof(pre));
head=tail=1;
q[head]=s;
pre[s]=1;
while(head<=tail)
{
int u=q[head++];
for(int i=h[u];i>-1;i=w[i].next)
{
int to=w[i].to;
if(w[i].d>0&&!pre[to])
{
pre[to]=pre[u]+1;
if(to==t) return true;
q[++tail]=to;
}
}
}
return false;
}
int dfs(int u,int p)
{
if(u==t||p==0) return p;
int r=p;
for(int i=h[u];i>-1;i=w[i].next)
{
if(r&&w[i].d&&pre[w[i].to]==pre[u]+1)
{
int p2=dfs(w[i].to,min(r,w[i].d));
if(p2)
{
w[i].d-=p2;
w[i^1].d+=p2;
r-=p2;
}
if(!r) return p;
}
}
if(p==r) pre[u]=0;
return p-r;
}
void Dinic()
{
while(bfs())
{
ans+=dfs(s,0x3f3f3f3f);
}
}
void init()
{
memset(h,-1,sizeof(h));
cnt=-1;
}
int main()
{
init();
scanf("%d%d",&n,&m);
s=0,t=2*n+1;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y+n,1);
add(y+n,x,0);
}
for(int i=1;i<=n;i++)
{
add(0,i,1);
add(i,0,0);
add(n+i,t,1);
add(t,n+i,0);
}
Dinic();
if(ans) printf("%d",ans);
else printf("NO SOLUTION");
}