NK 飞行员配对方案问题 网络流
http://acm.nankai.edu.cn/p2121.html
南开的24道网络流里的第一个 汉语题目 哈哈
二分匹配,增加一个源点S 一个汇点T 然后按最大流算 dinic
下面用矩阵和链表加边做的,两种写法目前当模板了
(一)用矩阵存储 运行时间 0MS
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<cstring>
#define Min(a,b)a<b?a:b
#define inf 100000
using namespace std;
int map[102][102],level[102];
int m,n,SUM,mark;
int dfs(int x,int Cap)
{
if(x==n+1)
return Cap;
int i,temp,tt,y=0;
for(i=1;i<=n+1;i++)
{
if(level[i]==level[x]+1&&Cap>y&&map[x][i]>0)
{
temp=Min(Cap-y,map[x][i]);
if(temp==0)continue;
tt=dfs(i,temp);
map[x][i]-=tt;
map[i][x]+=tt;
y+=tt;
}
}
return y;
}
int bfs()
{
int tt,k;
queue<int>qu;
memset(level,-1,sizeof(level));
level[0]=0;
qu.push(0);
while(!qu.empty())
{
tt=qu.front();
qu.pop();
for(k=1;k<=n+1;k++)
if(map[tt][k]>0&&level[k]==-1)
{
level[k]=level[tt]+1;
qu.push(k);
}
}
if(level[n+1]!=-1)return 1;
else return 0;
}
void dinic()
{
SUM=0;
mark=0;
while(bfs())
{
SUM+=dfs(0,inf);
}
return ;
}
void print()
{
if(SUM==0)
{
printf("No Solution!\n");
return ;
}
int i,j;
printf("%d\n",SUM);
for(i=0;i<=m;i++)//这方法开始没想到,看的别人的 还是对网络流了解不深
for(j=m+1;j<=n+1;j++)
if(map[i][j]==0&&i!=0&&j!=n+1)
printf("%d %d\n",i,j);
return ;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int i,j;
memset(map,-1,sizeof(map));
for(i=1;i<=m;i++)
{
map[0][i]=1;
map[i][0]=0;
}
for(i=m+1;i<=n;i++)
{
map[i][n+1]=1;
map[n+1][i]=0;
}
while(~scanf("%d%d",&i,&j))
{
if(i==-1&&j==-1)break;
map[i][j]=1;
map[j][i]=0;
}
dinic();
print();
}
return 0;
}
(二)链表,加边
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<cstring>
#define Min(a,b)a<b?a:b
#define inf 1000
using namespace std;
int level[102],head[102];
int m,n,s_edge,SUM;
struct Edge
{
int from,to,w,next;
}edge[12002];
void addedge(int u,int v, int ww )
{
s_edge++;
edge[s_edge].from=u;
edge[s_edge].to=v;
edge[s_edge].w=ww;
edge[s_edge].next=head[u];
head[u]=s_edge;
s_edge++;
edge[s_edge].from=v;
edge[s_edge].to=u;
edge[s_edge].w=0;
edge[s_edge].next=head[v];
head[v]=s_edge;
}
int dfs(int x,int Cap)
{
if(x==n+1)return Cap;
int y=0,t,temp,To;
for(t=head[x];t!=-1;t=edge[t].next)
{ To=edge[t].to;
if(level[To]==level[x]+1&&edge[t].w>0&&Cap-y>0)
{
temp=Min(Cap-y,edge[t].w);
int tt=dfs(To,temp);
edge[t].w-=tt;
edge[t^1].w+=tt;
y+=tt;
}
}
return y;
}
int bfs()
{
int t,To,tt;
queue<int>qu;
memset(level,-1,sizeof(level));
level[0]=0;
qu.push(0);
while(!qu.empty())
{
tt=qu.front();
qu.pop();
for(t=head[tt];t!=-1;t=edge[t].next)
{
To=edge[t].to;
if(level[To]==-1&&edge[t].w>0)
{
level[To]=level[tt]+1;
qu.push(To);
}
}
}
if(level[n+1]!=-1)return 1;
else return 0 ;
}
void dinic()
{
SUM=0;
while(bfs())
{
SUM+=dfs(0,inf);
}
return ;
}
void print()
{
if(SUM==0)
{
printf("No Solution!\n");
return ;
}
int i,j;
printf("%d\n",SUM);
for(i=0;i<=s_edge;i+=2)
if(edge[i].w==0&&edge[i].from!=0&&edge[i].to!=n+1)
printf("%d %d\n",edge[i].from,edge[i].to);
return ;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
int i,j;
s_edge=-1;
memset(head,-1,sizeof(head));
//memset(head,0,sizeof(head));错误,特别注意!!!
for(i=1;i<=m;i++)
addedge(0,i,1);//源点是0
for(i=m+1;i<=n;i++)
addedge(i,n+1,1);//n+1是汇点
while(~scanf("%d%d",&i,&j))
{
if(i==-1&&j==-1)break;
addedge(i,j,1);
}
dinic();
print();
}
return 0;
}

浙公网安备 33010602011771号