BZOJ 3876: [Ahoi2014&Jsoi2014]支线剧情

每条边流量至少为 \(1\)
直接套用有源汇上下界最小费用可行流

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) >> 1)
#define ll long long
#define db double
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define Edg int ccnt=1,head[N],to[N*2],ne[N*2];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[N*2],ne[N*2],c[N*2];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1e9 + 7;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2) {int ans = 1; for (; b; a = 1LL * a * a % MOD, b >>= 1)if (b & 1)ans = 1LL * ans * a % MOD; return ans % MOD;}
int gcd(int a, int b) { while (b) { a %= b; std::swap(a, b); } return a; }

const int N = 333, E = 2e4 + 7;
const int INF = 0x3f3f3f3f;
int n;

namespace MCF {
	struct Edge { int v, ne, f, c; } e[E];
	int n, head[N], cnt = 1, path[N], dis[N];
	bool inq[N];
	inline void add(int u, int v, int f, int c) {
		e[++cnt].v = v; e[cnt].f = f; e[cnt].ne = head[u]; e[cnt].c = c; head[u] = cnt;
		e[++cnt].v = u; e[cnt].f = 0; e[cnt].ne = head[v]; e[cnt].c = -c; head[v] = cnt;
	}
	bool spfa(int s, int t) {
		for (int i = 0; i <= t; i++) path[i] = -1, dis[i] = INF, inq[i] = 0;
		std::queue<int> que;
		que.push(s);
		dis[s] = 0;
		inq[s] = 1;
		while (!que.empty()) {
			int u = que.front(); que.pop();
			inq[u] = 0;
			for (int i = head[u]; i; i = e[i].ne) {
				int v = e[i].v, f = e[i].f;
				if (f && dis[v] > dis[u] + e[i].c) {
					dis[v] = dis[u] + e[i].c;
					path[v] = i;
					if (!inq[v]) {
						inq[v] = 1;
						que.push(v);
					}
				}
			}
		}
		return dis[t] != INF;
	}
	int mcf(int s, int t) {
		int ans = 0;
		while (spfa(s, t)) {
			int x = INF;
			for (int i = path[t]; ~i; i = path[e[i ^ 1].v]) x = std::min(x, e[i].f);
			for (int i = path[t]; ~i; i = path[e[i ^ 1].v]) e[i].f -= x, e[i ^ 1].f += x;
			ans += dis[t] * x;
		}
		return ans;
	}
}
int d[N];

int main() {
	scanf("%d", &n);
	int ans = 0;
	int s = 0, t = n + 2;
	rep (i, 1, n + 1) {
		int x;
		scanf("%d", &x);
		while (x--) {
			int v, c;
			scanf("%d%d", &v, &c);
			MCF::add(i, v, INF, c);
			d[i]--; d[v]++;
			ans += c;
		}
		MCF::add(i, n + 1, INF, 0);
	}
	rep (i, 1, n + 1) {
		if (d[i] > 0) MCF::add(s, i, d[i], 0);
		if (d[i] < 0) MCF::add(i, t, -d[i], 0);
	}
	MCF::add(n + 1, 1, INF, 0);
	printf("%d\n", ans + MCF::mcf(s, t));
	return 0;
}
posted @ 2020-02-25 23:56  Mrzdtz220  阅读(92)  评论(0编辑  收藏  举报