Description:
1<=n<=50
题解:
我的网络流学的怎么这么菜啊,GDOI时也是网络流的题一分没有。
好吧看到n<=50时的时候我就根本没有想过这是个流,就想着乱搞去了。
首先确定一个 O ( 2 n ∗ n 2 ) O(2^n*n^2) O(2n∗n2)的做法,就是我们枚举一些点,判断它们是否能够作为turpo序一个区间。
判断条件也比较好想: 不 存 在 i , j , k , 使 i , j ∈ S , k ∉ S , 且 i 能 通 过 k 到 j 不存在i,j,k,使i,j∈S,k∉S,且i能通过k到j 不存在i,j,k,使i,j∈S,k∈/S,且i能通过k到j
也就是对一条路径上的点,一定是先不选,然后选,然后不选。
对每一个点 x x x拆成 x 1 , x 2 x1,x2 x1,x2
考虑连边 S − > x 1 − > x 2 − > T S->x1->x2->T S−>x1−>x2−>T
割那条边表示分到哪段。
注意若原图有边 x − > y x->y x−>y,则x选的段<=y选的段。
所以 x 1 − > y 1 , x 2 − > y 2 , r = ∞ x1->y1,x2->y2,r=∞ x1−>y1,x2−>y2,r=∞
然后就是权值有正有负,那么可以先假设选了所有的正权点,那么 S − > x 1 , x 2 − > T S->x1,x2->T S−>x1,x2−>T的 r = a [ x ] r=a[x] r=a[x]
假设不选负权点, x 1 − > x 2 , r = − a [ x ] x1->x2,r=-a[x] x1−>x2,r=−a[x]
A n s = ∑ a [ x ] > 0 a [ x ] − 最 小 割 Ans=\sum_{a[x]>0}a[x]-最小割 Ans=∑a[x]>0a[x]−最小割
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
#define ul unsigned long long
using namespace std;
const int N = 1e5 + 5;
int fi[N], nt[N], to[N], r[N], tot = 1;
void link(int x, int y, int z) {
nt[++ tot] = fi[x], to[tot] = y, r[tot] = z, fi[x] = tot;
nt[++ tot] = fi[y], to[tot] = x, r[tot] = 0, fi[y] = tot;
}
int n, m, a[51], x, y;
int S, T, co[N], d[N], cur[N], ans;
int dg(int x, int flow) {
if(x == T) return flow;
int use = 0;
for(int i = cur[x]; i; cur[x] = i = nt[i])
if(d[x] == d[to[i]] + 1 && r[i]) {
int tmp = dg(to[i], min(flow - use, r[i]));
r[i] -= tmp, r[i ^ 1] += tmp, use += tmp;
if(use == flow) return use;
}
cur[x] = fi[x];
if(!(-- co[d[x]])) d[S] = T;
++ co[++ d[x]];
return use;
}
int main() {
freopen("san.in", "r", stdin);
freopen("san.out", "w", stdout);
scanf("%d %d", &n, &m);
S = 2 * n + 1; T = S + 1;
fo(i, 1, n) {
scanf("%d", &a[i]);
if(a[i] > 0) link(S, i, a[i]), link(i + n, T, a[i]), ans += a[i];
else link(i, i + n, -a[i]);
}
fo(i, 1, m) scanf("%d %d", &x, &y), link(x, y, 1 << 30), link(x + n, y + n, 1 << 30);
co[0] = T;
while(d[S] < T) ans -= dg(S, 1 << 30);
pp("%d", ans);
}