day20T3改错记

题目描述

两个点集(A)(B),有(m)条边,每条边连接(A)中的一个点和(B)中的一个点

每个点有属性(t)(只能是(0)或者(1)),若(a in A, b in B, t_a = t_b),且(a, b)之间有边,则(a)(b)可以匹配

(A)中每个点的(t)已知,(B)中每个点的(t)未知,问在所有可能的情况下,(A)(B)的最大匹配的最小是多少

(|A|, |B| le 2000, m le 5000)

解析

奇妙的网络流建图……

(A)中的点分为(t)(0)(t)(1)分成两部分(A_0, A_1)(S)(A_0)中每个点连容量为(1)的边,(A_1)中每个点向(T)连容量为(1)的边

(B)中每个点拆成(b_0, b_1)两个点,(b_0)(b_1)连一条容量为(1)的边

(A_0)中每个点向能匹配的(b_0)连容量(inf)的边,每个(b_1)(A_1)中能匹配的点连容量(inf)的边

跑一遍最小割就是答案

其实依然不太清楚为什么这么连边……

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define MAXN 2005

typedef long long LL;
const int inf = 0x3f3f3f3f;
struct Graph {
	struct Edge {
		int v, next, cap;
		Edge(int _v = 0, int _n = 0, int _c = 0):v(_v), next(_n), cap(_c) {}
	} edge[MAXN << 4];
	int head[MAXN << 2], cur[MAXN << 2], dep[MAXN << 2], cnt;
	void init() { memset(head, -1, sizeof head); cnt = 0; }
	void add_edge(int u, int v, int c) { edge[cnt] = Edge(v, head[u], c); head[u] = cnt++; }
	void insert(int u, int v, int c) { add_edge(u, v, c); add_edge(v, u, 0); }
	bool bfs();
	int dfs(int, int);
	int dinic();
};

char gc();
int read();

int N, M, K, t[MAXN];
Graph G;

int main() {
	freopen("deadline.in", "r", stdin);
	freopen("deadline.out", "w", stdout);

	N = read(), M = read(), K = read();
	G.init();
	for (int i = 1; i <= N; ++i) {
		t[i] = read();
		if (t[i]) G.insert(i, N + (M << 1) + 1, 1);
		else G.insert(0, i, 1);
	}
	while (K--) {
		int x = read(), y = read();
		if (t[x]) G.insert(N + M + y, x, inf);
		else G.insert(x, N + y, inf);
	}
	for (int i = 1; i <= M; ++i) G.insert(N + i, N + M + i, 1);
	printf("%d
", G.dinic());

	return 0;
}
inline char gc() {
	static char buf[1000000], *p1, *p2;
	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
	return p1 == p2 ? EOF : *p2++;
}
inline int read() {
	int res = 0; char ch = gc();
	while (ch < '0' || ch > '9') ch = gc();
	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();
	return res;
}
bool Graph::bfs() {
	memset(dep, 0, sizeof dep);
	int que[MAXN << 2], hd = 0, tl = 0;
	que[tl++] = 0, dep[0] = 1;
	while (hd < tl) {
		int p = que[hd++];
		if (p == N + (M << 1) + 1) return 1;
		for (int i = head[p]; ~i; i = edge[i].next)
			if (edge[i].cap && !dep[edge[i].v]) {
				dep[edge[i].v] = dep[p] + 1;
				que[tl++] = edge[i].v;
			}
	}
	return 0;
}
int Graph::dfs(int u, int max_flow) {
	if (u == N + (M << 1) + 1) return max_flow;
	int res = 0;
	for (int &i = cur[u]; ~i; i = edge[i].next)
		if (edge[i].cap && dep[edge[i].v] == dep[u] + 1) {
			int d = dfs(edge[i].v, std::min(max_flow, edge[i].cap));
			if (d) {
				res += d, max_flow -= d;
				edge[i].cap -= d, edge[i ^ 1].cap += d;
				if (!max_flow) break;
			}
		}
	if (!res) dep[u] = -1;
	return res;
}
int Graph::dinic() {
	int res = 0;
	while (bfs()) {
		memcpy(cur, head, sizeof head);
		res += dfs(0, inf);
	}
	return res;
}
//Rhein_E 100pts
原文地址:https://www.cnblogs.com/Rhein-E/p/10585142.html