飞行员配对方案
题目链接:Click Here~
算法分析:
本题有两种做法。
一、基础的二分匹配。求解最大匹配即答案。
二、基础网络流。求解最大流即为匹配总数,而满流的边即为有匹配关系。
二分代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100 + 5;
vector<int> G[maxn];
int link[maxn];
bool used[maxn];
int n,m;
void Init()
{
for(int i = 0;i < maxn;++i)
G[i].clear();
}
void AddEdge(int from,int to)
{
G[from].push_back(to);
}
bool dfs(int u)
{
for(int i = 0;i < (int)G[u].size();++i){
int v = G[u][i];
if(!used[v]){
used[v] = true;
if(link[v]==-1||dfs(link[v])){
link[v] = u; //printf("%d ---> %d\n",u,v);
return true;
}
}
}
return false;
}
int Find()
{
int res = 0;
memset(link,-1,sizeof(link));
for(int i = 1;i <= n;++i){
memset(used,false,sizeof(used));
if(dfs(i))res++;
}
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int x,y;
Init();
while(scanf("%d%d",&x,&y),(x!=-1&&y!=-1)){
AddEdge(x,y);
}
int res = Find();
if(!res)
puts("No Solution!");
else{
printf("%d\n",res);
for(int i = n+1;i <= m;++i){
if(link[i]!=-1)
printf("%d %d\n",link[i],i);
}
}
}
return 0;
}
网络流版(Dinic):
注意建边的时候是又向图的。不是双向的,我一开始建成了无向图,wrong了一次。(其实,我也不懂得为什么不能双向的。如果,你知道的话,可以给我留言。)
#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100+5;
const int INF = 200;
struct Edge{
int from,to,cap,flow;
};
vector<Edge> edges;
vector<int> G[maxn];
int d[maxn],cur[maxn];
bool vst[maxn];
int n,m,s,t;
void Init()
{
for(int i = 0;i < maxn;++i)
G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back((Edge){from,to,cap,0});
edges.push_back((Edge){to,from,0,0});
int sz = edges.size();
G[from].push_back(sz-2);
G[to].push_back(sz-1);
}
//构造层次图
bool BFS()
{
memset(vst,false,sizeof(vst));
queue<int> Q;
Q.push(s);
d[s] = 0;
vst[s] = true;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i = 0;i < (int)G[u].size();++i){
Edge& e = edges[G[u][i]];
if(!vst[e.to]&&e.cap > e.flow){
d[e.to] = d[u]+1;
vst[e.to] = true;
Q.push(e.to);
}
}
}
return vst[t];
}
//增广
int DFS(int u,int a)
{
if(u==t||a==0)
return a;
int f,flow = 0;
for(int& i = cur[u];i < (int)G[u].size();++i){
Edge& e = edges[G[u][i]];
if(d[e.to]==d[u]+1&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
e.flow += f;
edges[G[u][i]^1].flow -= f;
flow += f;
a -= f;
if(a==0)break;
}
}
return flow;
}
int Maxflow()
{
int flow = 0;
while(BFS()){
memset(cur,0,sizeof(cur));
flow += DFS(s,INF);
}
return flow;
}
int main()
{
while(~scanf("%d%d",&n,&m)){
Init();
int x,y;
while(scanf("%d%d",&x,&y),(x!=-1&&y!=-1)){
AddEdge(x,y,1);
// AddEdge(y,x,1);
}
s = 0,t = m+1;
for(int i = 1;i <= n;++i)AddEdge(s,i,1);
for(int i = n+1;i <= m;++i)AddEdge(i,t,1);
int res = Maxflow();
if(res<=0)
puts("No Solution!");
else{
printf("%d\n",res);
int sz = edges.size();
for(int i = 0;i < sz;i += 2){
Edge& e = edges[i];
if(e.flow == 1&&e.from!=s&&e.to!=t)
printf("%d %d\n",e.from,e.to);
}
}
}
return 0;
}