网络流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");
}
原文地址:https://www.cnblogs.com/zzz-hhh/p/13424639.html