zoukankan      html  css  js  c++  java
  • 网络流24题

    前言

    目录在右边
    剩下的先咕咕咕,以后总会有的.

    P2756 飞行员配对方案问题

    传送门

    思路

    思路和下一个题差不多,差在二分图一边是外籍人,一边是英国人

    code

    #include <queue>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define N 20000
    #define M 1010
    
    using namespace std;
    const ll inf = 2004072600;
    int n, m, x, y;
    ll d, ans, dis[N];
    int add_edge = 1, now[N], head[N];
    struct node {
    	int next, to;
    	ll val;
    }edge[N];
    
    ll read() {
    	int s = 0, f = 0; char ch = getchar();
    	while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void add(int from, int to, int dis) {
    	edge[++add_edge].next = head[from];
    	edge[add_edge].to = to;
    	edge[add_edge].val = dis;
    	head[from] = add_edge;
    	
    	edge[++add_edge].next = head[to];
    	edge[add_edge].to = from;
    	edge[add_edge].val = 0;
    	head[to] = add_edge;
    }
    
    inline int bfs() {
    	for (int i = 0; i <= n + 1; i++) dis[i] = inf;
    	queue<int> q; q.push(0), dis[0] = 0, now[0] = head[0];
    	while (!q.empty()) {
    		int x = q.front(); q.pop();
    		for (int i = head[x]; i; i = edge[i].next) {
    			int to = edge[i].to;
    			if (edge[i].val > 0 && dis[to] == inf) {
    				q.push(to);
    				now[to] = head[to];
    				dis[to] = dis[x] + 1;
    				if (to == n + 1) return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    int dfs(int x, ll sum) {
    	if (x == n + 1) return sum;
    	ll k, res = 0;
    	for (int i = now[x]; i && sum; i = edge[i].next) {
    		now[x] = i;
    		int to = edge[i].to;
    		if (edge[i].val > 0 && (dis[to] == dis[x] + 1)) {
    			k = dfs(to, min(sum, edge[i].val));
    			if (k == 0) dis[to] = inf;
    			edge[i].val -= k;
    			edge[i ^ 1].val += k;
    			res += k, sum -= k;
    		}
    	}
    	return res;
    }
    
    int main() {
    	m = read(), n = read();
    	x = read(), y = read();
    	while (x != -1 && y != -1) {
    		add(x, y, 0x3f3f3f3f);
    		x = read(), y = read();
    	}
    	for (int i = 1; i <= m; i++) add(0, i, 1);
    	for (int i = m + 1; i <= n; i++) add(i, n + 1, 1);
    	while (bfs())
    		ans += dfs(0, inf);
    	cout << ans << "
    ";
    	for (int i = 2; i <= add_edge; i += 2) {
    		if (edge[i].to != 0 && edge[i ^ 1].to != 0) 
    		if (edge[i].to != n + 1 && edge[i ^ 1].to != n + 1) 
    		if (edge[i ^ 1].val != 0) 
    			printf("%d %d
    ", edge[i ^ 1].to, edge[i].to); 
    	}
    	return 0;
    }
    

    P3254 圆桌问题

    传送门

    思路

    可以很明显的想到,这个题我们可以网络流跑二分图(因为很快)

    我们把左边看成单位,右边看成第几个桌子

    因为题目中要求我们希望从同一个单位来的代表不在同一个餐桌就餐

    所以第一步就是让每一个单位向每一个桌子连一条边权为1的边。

    第二步:开一个超级源点,让每一个超级源点都往单位连一条边权为(r_i)的边,代表流量必须是这么大。

    第三步:开一个超级汇点,让每一个桌子都往超级汇点连一条边权为(c_i)的边,代表着每个人都必须有桌子坐

    最后我们跑一边最大流,然后看看能不能做开,即最大流量是不是与总人数相等

    code

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define N 1000010
    #define M 1010
    
    using namespace std;
    const ll inf = 2004072600;
    int n, m, x, y;
    ll d, ans, dis[N];
    int add_edge = 1, now[N], head[N];
    struct node {
    	int next, to;
    	ll val;
    }edge[N];
    
    int read() {
    	int s = 0, f = 0; char ch = getchar();
    	while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void add(int from, int to, ll dis) {
    	edge[++add_edge].next = head[from];
    	edge[add_edge].to = to;
    	edge[add_edge].val = dis;
    	head[from] = add_edge;
    	
    	edge[++add_edge].next = head[to];
    	edge[add_edge].to = from;
    	edge[add_edge].val = 0;
    	head[to] = add_edge;
    }
    
    inline int bfs() {
    	for (int i = 0; i <= n + m + 1; i++) dis[i] = inf;
    	queue<int> q; q.push(0), dis[0] = 0, now[0] = head[0];
    	while (!q.empty()) {
    		int x = q.front(); q.pop();
    		for (int i = head[x]; i; i = edge[i].next) {
    			int to = edge[i].to;
    			if (edge[i].val > 0 && dis[to] == inf) {
    				q.push(to);
    				now[to] = head[to];
    				dis[to] = dis[x] + 1;
    				if (to == n + m + 1) return 1; 
    			}
    		}
    	}
    	return 0;
    }
    
    int dfs(int x, ll sum) {
    	if (x == n + m + 1) return sum;
    	ll k, res = 0;
    	for (int i = now[x]; i && sum; i = edge[i].next) {
    		now[x] = i;
    		int to = edge[i].to;
    		if (edge[i].val > 0 && (dis[to] == dis[x] + 1)) {
    			k = dfs(to, min(sum, edge[i].val));
    			if (k == 0) dis[to] = inf;
    			edge[i].val -= k;
    			edge[i ^ 1].val += k;
    			res += k, sum -= k;
    		}
    	}
    	return res;
    }
    
    void link() {
    	for (int i = 1; i <= n; i++)
    		for (int j = n + 1; j <= n + m; j++)
    			add(i, j, 1);
    	for (int i = 1, r; i <= n; i++) {
    		r = read();
    		add(0, i, r); ans += r;
    	}
    	for (int i = n + 1, c; i <= n + m; i++) {
    		c = read();
    		add(i, n + m + 1, c);
    	}
    }
    
    int main() {
    	n = read(), m = read();
    	link();
    	while (bfs())
    		ans -= dfs(0, inf);	
    	if (ans == 0) {
    		puts("1");	
    		for (int i = 1; i <= n; i++) {
    			for (int j = head[i]; j; j = edge[j].next) {
    				int to = edge[j].to;
    				if (to > n && to <= n + m && !edge[j].val)
    					printf("%d ", to - n);
    			}
    			puts("");
    		}
    	} else puts("0");
    }
    
  • 相关阅读:
    打印机无法访问打印机怎么连
    IDEA 2018 LICENSE SERVER
    idea 项目打包发布
    Oracle的关于小数的使用
    js代码实现购物车效果
    通过shell定时备份数据库
    (二)Linux实操之——网络配置、进程管理、服务管理、组管理、YUM
    (一)Linux实操之——权限、任务调度、磁盘分区
    idea搭建简易ssm项目
    idea右键无法新建Java Class
  • 原文地址:https://www.cnblogs.com/zzz-hhh/p/13424639.html
Copyright © 2011-2022 走看看