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


    题目描述

    英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

    输入输出格式

    输入格式:

    第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行员总数(n<100);m 是外籍飞行员数(m<=n)。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。

    接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。最后以 2个-1 结束。

    输出格式:

    第 1 行是最佳飞行员配对方案一次能派出的最多的飞机数 M。接下来 M 行是最佳飞行员配对方案。每行有 2个正整数 i 和 j,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。

    输入输出样例

    输入样例#1: 复制
    5 10
    1 7
    1 8
    2 6
    2 9
    2 10
    3 7
    3 8
    4 7
    4 8
    5 10
    -1 -1
    输出样例#1: 复制
    4
    1 7
    2 9
    3 8
    5 10 

    这题没什么好讲的,就是一个裸的最大的二分图匹配。
    恶心的一点就是打印方案。
    网络流可以解决二分图问题;

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <vector>
      4 #include <queue>
      5 #include <cstring>
      6 #include <string>
      7 #include <map>
      8 using namespace std;
      9 const int maxn = 2e5 + 10;
     10 const int INF = 1e9 + 10;
     11 typedef long long LL;
     12 struct node {
     13     int from, to, cap, flow;
     14 };
     15 struct Dinic {
     16     int n, m, s, t;
     17     vector<node>nodes;
     18     vector<int>g[maxn];
     19     int vis[maxn];
     20     int d[maxn];
     21     int cur[maxn];
     22     void clearall(int n) {
     23         for (int i = 0 ; i < n ; i++) g[i].clear();
     24         nodes.clear();
     25     }
     26     void clearflow() {
     27         int len = nodes.size();
     28         for (int i = 0 ; i < len ; i++) nodes[i].flow = 0;
     29     }
     30     void add(int from, int to, int cap) {
     31         nodes.push_back((node) {
     32             from, to, cap, 0
     33         });
     34         nodes.push_back((node) {
     35             to, from, 0, 0
     36         });
     37         m = nodes.size();
     38         g[from].push_back(m - 2);
     39         g[to].push_back(m - 1);
     40     }
     41     bool bfs() {
     42         memset(vis, 0, sizeof(vis));
     43         queue<int>q;
     44         q.push(s);
     45         d[s] = 0;
     46         vis[s] = 1;
     47         while(!q.empty()) {
     48             int x = q.front();
     49             q.pop();
     50             int len = g[x].size();
     51             for (int i = 0 ; i < len ; i++) {
     52                 node &e = nodes[g[x][i]];
     53                 if (!vis[e.to] && e.cap > e.flow ) {
     54                     vis[e.to] = 1;
     55                     d[e.to] = d[x] + 1;
     56                     q.push(e.to);
     57                 }
     58             }
     59         }
     60         return vis[t];
     61     }
     62     int dfs(int x, int a) {
     63         if  (x == t || a == 0) return a;
     64         int flow = 0, f, len = g[x].size();
     65         for (int &i = cur[x] ; i < len ; i++) {
     66             node & e = nodes[g[x][i]];
     67             if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0 ) {
     68                 e.flow += f;
     69                 nodes[g[x][i] ^ 1].flow -= f;
     70                 flow += f;
     71                 a -= f;
     72                 if (a == 0) break;
     73             }
     74         }
     75         return flow;
     76     }
     77     int maxflow(int a, int b) {
     78         s = a;
     79         t = b;
     80         int flow = 0;
     81         while(bfs()) {
     82             memset(cur, 0, sizeof(cur));
     83             flow += dfs(s, INF);
     84         }
     85         return flow;
     86     }
     87     vector<int>mincut() {
     88         vector<int>ans;
     89         int len = nodes.size();
     90         for (int i = 0 ; i < len ; i++) {
     91             node & e = nodes[i];
     92             if ( vis[e.from] && !vis[e.to] && e.cap > 0 ) ans.push_back(i);
     93         }
     94         return ans;
     95     }
     96     void reduce() {
     97         int len = nodes.size();
     98         for (int i = 0 ; i < len ; i++) nodes[i].cap -= nodes[i].flow;
     99     }
    100     void path() {
    101         int sz = nodes.size();
    102         for(int i = 0; i < sz; i += 2) {
    103             node & e = nodes[i];
    104             if(e.flow == 1 && e.from != s && e.to != t)
    105                 printf("%d %d
    ", e.from, e.to);
    106         }
    107     }
    108 } f;
    109 int main() {
    110     int n, m;
    111     scanf("%d%d", &m, &n);
    112     int x, y, s = 0, t = n + 1;
    113     while(1) {
    114         scanf("%d%d", &x, &y);
    115         if (x == -1 && y == -1 ) break;
    116         f.add(x, y, 1);
    117     }
    118     for (int i = 1 ; i <= n ; i++) {
    119         if (i <= m) f.add(0, i, 1);
    120         else f.add(i, n + 1, 1);
    121     }
    122     int ret = f.maxflow(0, n + 1);
    123     if (!ret) printf("No Solution!
    ");
    124     else {
    125         printf("%d
    ", ret);
    126         f.path();
    127     }
    128     return 0;
    129 }
  • 相关阅读:
    字符编码笔记:ASCII、Unicode和UTF8(转载)
    一文搞定CSS
    《中西方文华差异之渊源——王德峰》心得
    git一些命令
    Netty学习
    CAS概念和解析
    Node.js安装及环境配置之Windows篇
    如何卸载onedrive
    win10系统修改窗口边框颜色
    win10禁止插入U盘后自动打开
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/8988628.html
Copyright © 2020-2023  润新知