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;
}