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\n", 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
posted @ 2019-03-23 19:05  Rhein_E  阅读(115)  评论(0编辑  收藏  举报