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


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

    解题思路

    问题模型:二分图最大匹配
    转化模型:网络最大流

    这题我们用网络流来做。

    因为有多个飞行员,且是有向无环图,所以我们建立超级源点和超级汇点,这样才能用网络流去做。

    将超级源点与外籍飞行员(1)~(m)连流量为(1)的边,将英国飞行员(m+1)(n+m)与超级汇点连流量为(1)的边,然后将题目给出的边也连流量为(1)的边即可。

    之后再去跑最大流( ext{Dinic})算法,得出最大匹配数,最后输出时判断一下就行。

    1. 只判断正边,所以从第(0)条边开始判断,每次加(2)
    2. 判断当前边是否与汇点或源点相连,相连则跳过
    3. 判断边权是否为(0),为(0)则跳过

    如果满足了上述条件,输出即可,最后给出代码

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int m, n, cnt, opt, S, T, ans, head[A], d[A], q[A];
    struct node { int from, to, nxt, val; } e[A];
    
    inline void add(int from, int to, int val) {
    	e[cnt].to = to;
    	e[cnt].val = val;
    	e[cnt].nxt = head[from];
    	head[from] = cnt++;
    }
    
    inline bool makelevel(int s, int t) {
    	memset(d, 0, sizeof(d));
    	memset(q, 0, sizeof(q));
    	int l = 0, r = 0;
    	d[s] = 1; q[r++] = s;
    	while (l < r) {
    		int x = q[l++];
    		if (x == t) return true;
    		for (int i = head[x]; i != -1; i = e[i].nxt) {
    			if(d[e[i].to] == 0 && e[i].val) {
    				q[r++] = e[i].to;
    				d[e[i].to] = d[x] + 1;
    			}
    		}
    	}
    	return false;
    }
    
    int dfs(int x, int flow, int t) {
    	if (x == t) return flow;
    	int sum = 0;
    	for (int i = head[x]; i != -1; i = e[i].nxt) {
    		 if (e[i].val && d[e[i].to] == d[x] + 1) {
    		 	int tmp = dfs(e[i].to, min(flow - sum, e[i].val), t);
    		 	e[i].val -= tmp, e[i ^ 1].val += tmp;
    		 	sum += tmp;
    		 	if (sum == flow) return sum;
    		 }
    	}
    	return sum;
    }
    
    int main() {
    	m = read(), n = read();
    	S = 0, T = m + n + 1;
    	memset(head, -1, sizeof(head));
    	int x, y;
    	while (x != -1 && y != -1) {
    		add(x, y, 1), add(y, x, 0);
    		x = read(), y = read();
    	}
    	for (int i = 1; i <= m; i++) add(S, i, 1), add(i, S, 0);
    	for (int i = m + 1; i <= m + n; i++) add(i, T, 1), add(T, i, 0);
    	while (makelevel(S, T)) ans += dfs(S, inf, T);
    	cout << ans << '
    ';
    	for (int i = 0; i <= cnt; i += 2) {
    		if (e[i].to != S && e[i ^ 1].to != S)
            	if (e[i].to != T && e[i ^ 1].to != T)
            		if (e[i ^ 1].val != 0) {
                		cout <<  e[i ^ 1].to << " " << e[i].to << '
    ';
            		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    关于GET和POST请求的区别,最通俗全面的回答
    Mac常用命令行
    Jquery中的done() fail() then() $when()到底是什么
    聊聊HTML5中的Web Notification桌面通知
    css实现左右两个div等高
    css样式优先级计算规则
    vue获取后端数据放在created还是mounted方法里面?
    vue的provide和inject特性
    前端路由的实现原理
    Windows鼠标右键新建中增加新建md文件
  • 原文地址:https://www.cnblogs.com/loceaner/p/12307784.html
Copyright © 2020-2023  润新知