Loading

「刷题记录」POJ 3281

题目传送门:POJ 3281
记录自己做的第一道也是自己独立码出来的题
题目思路:将牛拆成两半,前一半与食物相连边,后一半与饮料相连边,牛的前一半与后一半相连边,它们的边权都为 \(1\),建立一个超级源点与每个食物相连边,建立一个超级汇点与每个饮料相连边,跑 \(\text{dinic}\) 最大流即可,这里我给所有的点重新附了一个编号,以防止建边时编号冲突,上代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;

inline ll read() {
	ll x = 0;
	int fg = 0;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		fg |= (ch == '-');
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + (ch ^ 48);
		ch = getchar();
	}
	return fg ? -x : x;
}

const int N = 1100;
const ll inf = 1e15;

int n, F, D, cnt, S, T;
ll maxflow;
int h[N << 2], f[N], d[N];
int frt[N], bak[N], idf[N], idd[N]; 
int cur[N], dep[N], inque[N];
queue<int> q;

struct edge {
	int v, nxt;
	ll w;
} e[4000010];

void add(int u, int v, ll w) {
	e[++ cnt].v = v;
	e[cnt].w = w;
	e[cnt].nxt = h[u];
	h[u] = cnt;
}

int bfs() {
	for (int i = 0; i <= T; ++ i) {
		dep[i] = 1e9;
		inque[i] = 0;
		cur[i] = h[i];
	}
	while (!q.empty()) {
		q.pop();
	}
	q.push(S);
	dep[S] = 0;
	inque[S] = 1;
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		inque[u] = 0;
		for (int i = h[u]; i; i = e[i].nxt) {
			int v = e[i].v;
			if (dep[v] > dep[u] + 1 && e[i].w) {
				dep[v] = dep[u] + 1;
				if (!inque[v]) {
					q.push(v);
					inque[v] = 1;
				}
				if (v == T)	return 1;
			}
		}
	}
	return 0;
}

ll dfs(int u, ll flow) {
	if (u == T) {
		maxflow += flow;
		return flow;
	}
	ll rlow, used = 0;
	for (int i = cur[u]; i; i = e[i].nxt) {
		cur[u] = i;
		int v = e[i].v;
		if (dep[v] == dep[u] + 1 && e[i].w) {
			if ((rlow = dfs(v, min(flow - used, e[i].w)))) {
				used += rlow;
				e[i].w -= rlow;
				e[i ^ 1].w += rlow;
				if (used == flow)	break;
			}
		}
	}
	return used;
}

int main() {
	int x;
	n = read(), F = read(), D = read();
	x = (n << 1) + F + D;
	T = x + 1, cnt = 1;
	for (int i = 1; i <= F; ++ i) {
		idf[i] = i;
		add(S, idf[i], 1);
		add(idf[i], S, 0);
	}
	for (int i = 1; i <= n; ++ i) {
		frt[i] = i + F;
		bak[i] = i + F + n;
		add(frt[i], bak[i], 1);
		add(bak[i], frt[i], 0);
	}
	for (int i = 1; i <= D; ++ i) {
		idd[i] = i + n + n + F;
		add(idd[i], T, 1);
		add(T, idd[i], 0);
	}
	for (int i = 1; i <= n; ++ i) {
		f[i] = read();
		d[i] = read();
		for (int j = 1; j <= f[i]; ++ j) {
			x = read();
			add(idf[x], frt[i], 1);
			add(frt[i], idf[x], 0);
		}
		for (int j = 1; j <= d[i]; ++ j) {
			x = read();
			add(bak[i], idd[x], 1);
			add(idd[x], bak[i], 0);
		}
	}
	while (bfs()) {
		dfs(S, inf);
	}
	printf("%lld\n", maxflow);
	return 0;
}
posted @ 2023-01-04 19:26  yi_fan0305  阅读(37)  评论(0编辑  收藏  举报