洛谷P2756:飞行员配对问题

题目描述

    说的是共有n个点,求前m个点与后n-m+1个点会有若干条路相连,求最大匹配程度。

   如下图:最大匹配度则为3(1-6,2-4,3-5(7));

洛谷P2756:飞行员配对问题_第1张图片

       这个问题就很好地转化为了二分图最大匹配的问题(ljy:那不是最大流求解,从源点像前m个点连一条流量为1的边,原始的边连是要连,但是流量要改成INF,再从剩下的节点中连一条流量为1到超级汇,(如下图所示)就好了!!!),但是题目的关键是求匹配方案(zzy:一脸懵逼。。),所以我们要想一点妙招来解决这个东西。

洛谷P2756:飞行员配对问题_第2张图片

妙招

       我们来建立一个数组叫match[i](0

贴代码

#include
#include
#include
#define INF 147483647


int n,m;
int first[200010];
struct edge{int y,next,d;};
edge s[400010];
int begin,end;
int len=1;
int match[100010];
int h[200010];
int f[200010];
int st=1,ed=2;


void ins(int x,int y,int d)
{
len++;
s[len].y=y;s[len].next=first[x];
s[len].d=d;first[x]=len;
}


int min(int x,int y)
{
return x0)
{
h[y]=h[x]+1;
f[ed]=y;
ed++;
if(ed==n+3) ed=1;
}
}
st++;
if(st==n+3) st=1;
}
if(h[end]!=0) return true;
return false;
}


int dfs(int x,int t)
{
if(x==end) return t;
int tot=0;
for(int i=first[x];i!=0;i=s[i].next)
{
if(tot==t) return t;
int y=s[i].y;
if(h[y]==h[x]+1)
{
int now=dfs(y,min(s[i].d,t-tot));
tot+=now;s[i].d-=now;s[i^1].d+=now;
if(now!=0 && x<=m && x>0)
match[x]=y;
}
}
if(tot==0) h[x]=0;
return tot;
}


int find_ans()
{
int ans=0;
while(bfs())
ans+=dfs(begin,INF);
return ans;
}


int main()
{
scanf("%d %d",&m,&n);
begin=0;end=n+1;
for(int i=1;i<=m;i++)
ins(begin,i,1),ins(i,begin,0);
for(int i=m+1;i<=n;i++)
ins(i,end,1),ins(end,i,0);
while(1)
{
int x,y;
scanf("%d %d",&x,&y);
if(x==-1 || y==-1) break;
ins(x,y,INF);ins(y,x,0);
}
int ans=find_ans();
if(ans==0)
printf("No Solution!");
else 
printf("%d\n",ans);
for(int i=1;i<=m;i++)
if(match[i]!=0) printf("%d %d\n",i,match[i]);
}


你可能感兴趣的:(洛谷P2756:飞行员配对问题)