2020牛客暑期多校训练营(第一场) I 1 or 2 (最大流)

题面:


题意
给定n个节点和m条边以及每个节点的期望度数,问是否可以通过删去一些边使每个节点都满足期望度数。
根据官方的解法应该是带花树的一般图匹配算法,但我不会 ,因此突发奇想可不可以转化为最大流的模型。


老套路,先拆分点,以样例三为例,我们把1拆成1和1’, 将2拆成2和2’, 将3拆成3和3’。如果一个节点的期望度数为2,我们就将i与S连一条流量为2的2边,再将i’与T连一条流量为2的边。其余点按如图所示的连接方法,最后求出最大流为2。
最后跑一遍最大流的板子,只要最后汇点的流量总和等于所有点的度数即源点流出的流量时,输出Yes,否则输出No。

AC Code

#include <bits/stdc++.h>
using namespace std;
const int N = 200 + 5;
const int M = 10000 + 5;
int n, m, a[N], cnt, h[N], s, t;
int cur[N], dep[N];
int maxflow, ss;
struct edge {
    
    
	int to, next, vi;
}e[2*M];

void add(int u, int v, int w) {
    
    
	e[cnt].to = v;
	e[cnt].vi = w;
	e[cnt].next = h[u];
	h[u] = cnt++;

	e[cnt].to = u;
	e[cnt].vi = 0;
	e[cnt].next = h[v];
	h[v] = cnt++;
}

bool bfs() {
    
    
	for (int i = 0; i <= 2*n+2; i++) cur[i] = h[i], dep[i] = -1;
	queue<int> q;
	q.push(s);
	dep[s] = 0;

	while (q.size()) {
    
    
		int u = q.front();
		q.pop();
		if (u == t) break;

		for (int i = h[u]; ~i; i = e[i].next) {
    
    
			int v = e[i].to;
			if (e[i].vi && dep[v] == -1) {
    
    
				dep[v] = dep[u] + 1;
				q.push(v);
			}
		}
	}
	if (dep[t] > -1) return true;
	else return false;
}

int dfs(int u, int mx) {
    
    
	int a;
	if (u == t) return mx;
	for (int i = cur[u]; ~i; i = e[i].next) {
    
    
		int v = e[i].to;
		cur[u] = i;
		if (e[i].vi&& dep[v] == dep[u] + 1 && (a = (dfs(v, min(mx, e[i].vi))))) {
    
    
			e[i].vi -= a;
			e[i ^ 1].vi += a;
			return a;
		}
	}
	return 0;
}

void dinic() {
    
    
	int res;
	while (bfs()) {
    
    
		res = dfs(s, 0x3f3f3f);
		if (!res) break;
		maxflow += res;
	}
}

int main() {
    
    
	while (cin >> n >> m) {
    
    
		memset(h, -1, sizeof h);
		maxflow = 0;
		cnt = 0;
		ss = 0;
		s = n * 2 + 1, t = n * 2 + 2;
		for (int i = 1; i <= n; i++) cin >> a[i], ss += a[i];

		for (int i = 0; i < m; i++) {
    
    
			int x, y;
			cin >> x >> y;
			add(x, y + n, 1);
			add(y, x + n, 1);
		}
		for (int i = 1; i <= n; i++) {
    
    
			if (a[i] == 2) {
    
    
				add(s, i, 2);
				add(i+n, t, 2);
			}
			else {
    
    
				add(s, i, 1);
				add(i+n, t, 1);
			}
		}

		dinic();

		if (maxflow == ss) cout << "Yes" << endl;
		else cout << "No" << endl;
	}
}

猜你喜欢

转载自blog.csdn.net/kaka03200/article/details/107498748