网络流24题-飞行员配对方案问题

题目链接:https://www.luogu.org/problemnew/show/P2756

经典的二分图最大匹配问题。

我们用最大流来做

首先从源点向外籍飞行员编号连容量为1的边,每个英国飞行员编号向汇点连容量为1的边,二分图内的边连容量为inf的边

跑一遍最大流,判断边是否有流量,即反向弧不为零的边

dinic算法

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 const int inf=0x3f3f3f3f; //int的最大值
  5 const int MAXN=1000,MAXM=100000; //N为点数,M为边数
  6 struct node
  7 {
  8     int v,nxt,f;
  9 }edge[MAXM*2+10];
 10 int S,T,tot,head[MAXN+10]; //S为源点,T为汇点
 11 void add(int u,int v,int c) //添加正向边和反向边
 12 {
 13     edge[++tot].v=v;    edge[tot].f=c;  edge[tot].nxt=head[u];  head[u]=tot;
 14     edge[++tot].v=u;    edge[tot].f=0;  edge[tot].nxt=head[v];  head[v]=tot;
 15 }
 16 void init()//初始化
 17 {
 18     memset(head,0,sizeof(head));
 19     tot=1;
 20 }
 21 queue<int>q;
 22 int depth[MAXN+10];
 23 bool bfs()
 24 {
 25     memset(depth,0,sizeof(depth));
 26     while(!q.empty()) q.pop();
 27     q.push(S);
 28     depth[S]=1;
 29     while(!q.empty())
 30     {
 31         int x=q.front();q.pop();
 32         for(int i=head[x];i;i=edge[i].nxt)
 33         {
 34             int v=edge[i].v;
 35             if(edge[i].f&&!depth[v])
 36             {
 37                 q.push(v);
 38                 depth[v]=depth[x]+1;
 39                 if(v==T)    return 1;
 40 
 41             }
 42         }
 43     }
 44     return 0;
 45 }
 46 int dfs(int x,int flow)
 47 {
 48     if(x==T)    return flow;
 49     int rest=flow,w;
 50     for(int i=head[x];i&&rest;i=edge[i].nxt)
 51     {
 52         int v=edge[i].v;
 53         if(edge[i].f&&depth[v]==depth[x]+1)
 54         {
 55             w=dfs(v,min(rest,edge[i].f));
 56             if(!w)  depth[v]=0;
 57             edge[i].f-=w;
 58             edge[i^1].f+=w;
 59             rest-=w;
 60         }
 61     }
 62     return flow-rest;
 63 }
 64 int dinic()
 65 {
 66     int flow,maxflow=0;
 67     while(bfs())
 68     {
 69         while(flow=dfs(S,inf))    maxflow+=flow;
 70     }
 71     return maxflow;
 72 }
 73 int main()
 74 {
 75     int n,m,x,y;
 76     init();
 77     scanf("%d%d",&m,&n);
 78     S=0;T=n+1;
 79     while(1)
 80     {
 81         scanf("%d%d",&x,&y);
 82         if(x==-1&&y==-1)    break;
 83         add(x,y,inf);
 84     }
 85     for(int i=1;i<=m;i++)   add(S,i,1);
 86     for(int i=m+1;i<=n;i++) add(i,T,1);
 87     int maxflow=dinic();
 88     if(maxflow==0)
 89     {
 90         printf("No Solution!\n");
 91         return 0;
 92     }
 93     printf("%d\n",maxflow);
 94     for(int i=2;i<=tot;i+=2)
 95     {
 96         if(edge[i].v!=S&&edge[i^1].v!=S&&edge[i].v!=T&&edge[i^1].v!=T&&edge[i^1].f!=0)
 97             printf("%d %d\n",edge[i^1].v,edge[i].v);
 98     }
 99     return 0;
100 }
View Code

 匈牙利算法

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int inf=0x3f3f3f3f;
 5 const int MAXN=10000;
 6 const int MAXM=100000;
 7 struct Edge
 8 {
 9     int to,nxt;
10 }edge[MAXM];
11 int head[MAXN],tot,match[MAXN];
12 bool vis[MAXN];
13 void init()
14 {
15     tot=0;
16     memset(head,-1,sizeof(head));
17 }
18 void addedge(int u,int v)
19 {
20     edge[tot].to=v; edge[tot].nxt=head[u];  head[u]=tot++;
21 }
22 bool dfs(int x)
23 {
24     for(int i=head[x];i!=-1;i=edge[i].nxt)
25     {
26         int y=edge[i].to;
27         if(!vis[y])
28         {
29             vis[y]=1;
30             if(!match[y]||dfs(match[y]))
31             {
32                 match[y]=x;
33                 return true;
34             }
35 
36         }
37     }
38     return false;
39 }
40 int solve(int N)
41 {
42     int ans=0;
43     memset(match,0,sizeof(match));
44     for(int i=0;i<N;i++)//点的编号为0~N-1
45     {
46         memset(vis,0,sizeof(vis));
47         if(dfs(i))  ans++;
48     }
49     return ans;
50 }
51 int n,m;
52 int main()
53 {
54     ios::sync_with_stdio(false);
55     cin.tie(0);cout.tie(0);
56     cin>>m>>n;
57     int x,y;
58     init();
59     while(1)
60     {
61         cin>>x>>y;
62         if(x==-1&&y==-1)    break;
63         addedge(x,y);
64     }
65     cout<<solve(n)<<endl;
66     for(int i=1;i<=n;i++)
67     {
68         if(match[i])
69             cout<<match[i]<<" "<<i<<endl;//注意方向
70     }
71     return 0;
72 }
View Code

 

posted @ 2018-10-02 11:05  Scott_Wong  阅读(148)  评论(0)    收藏  举报