传送门: https://ac.nowcoder.com/acm/contest/369/F
题意
思路
数
据
范
围
不
大
,
而
且
存
在
二
元
限
制
关
系
,
考
虑
网
络
流
。
数据范围不大,而且存在二元限制关系,考虑网络流。
数据范围不大,而且存在二元限制关系,考虑网络流。
假 如 x 和 y 存 在 二 元 限 制 关 系 , 所 以 考 虑 x 和 y 是 否 选 取 。 假如x和y存在二元限制关系,所以考虑x和y是否选取。 假如x和y存在二元限制关系,所以考虑x和y是否选取。
如 果 考 虑 选 取 呢 ? 最 小 割 ! 设 与 源 点 s 在 一 部 分 的 点 不 取 , 与 汇 点 在 一 部 分 的 点 取 。 如果考虑选取呢?最小割!设与源点s在一部分的点不取,与汇点在一部分的点取。 如果考虑选取呢?最小割!设与源点s在一部分的点不取,与汇点在一部分的点取。
将 所 有 的 w 和 v 0 和 v 1 加 起 来 , 然 后 把 最 小 割 认 为 是 代 价 , 答 案 就 是 s u m − 最 小 割 ( 最 小 代 价 ) 。 将所有的w和v_0和v_1加起来,然后把最小割认为是代价,答案就是sum-最小割(最小代价)。 将所有的w和v0和v1加起来,然后把最小割认为是代价,答案就是sum−最小割(最小代价)。
设 w x , w y , v 0 , v 1 , v 2 表 示 x 的 权 值 , y 的 权 值 , x 和 y 都 选 的 权 值 , x 和 y 都 不 选 的 权 值 , x 和 y 只 选 一 个 的 权 值 。 设w_x,w_y,v_0,v_1,v_2表示x的权值,y的权值,x和y都选的权值,x和y都不选的权值,x和y只选一个的权值。 设wx,wy,v0,v1,v2表示x的权值,y的权值,x和y都选的权值,x和y都不选的权值,x和y只选一个的权值。
为 什 么 没 有 v 2 ? 因 为 v 2 是 扣 除 的 , 不 是 代 价 , v 2 要 在 我 们 最 小 割 模 型 中 会 被 算 进 去 , 最 后 会 减 掉 。 为什么没有v_2?因为v_2是扣除的,不是代价,v_2要在我们最小割模型中会被算进去,最后会减掉。 为什么没有v2?因为v2是扣除的,不是代价,v2要在我们最小割模型中会被算进去,最后会减掉。
则 对 于 上 面 的 模 型 , 最 小 割 有 四 种 : 则对于上面的模型,最小割有四种: 则对于上面的模型,最小割有四种:
- x 和 y 都 选 , 最 小 割 为 a + c = v 1 x和y都选,最小割为a+c=v_1 x和y都选,最小割为a+c=v1
- x 和 y 都 不 选 , 最 小 割 为 b + d = w x + w y + v 0 x和y都不选,最小割为b+d=w_x+w_y+v_0 x和y都不选,最小割为b+d=wx+wy+v0
- x 选 , y 不 选 , 最 小 割 为 a + f + d = w y + v 0 + v 1 + v 2 x选,y不选,最小割为a+f+d=w_y+v_0+v_1+v_2 x选,y不选,最小割为a+f+d=wy+v0+v1+v2
- x 不 选 , y 选 , 最 小 割 为 c + e + b = w x + v 0 + v 1 + v 2 x不选,y选,最小割为c+e+b=w_x+v_0+v_1+v_2 x不选,y选,最小割为c+e+b=wx+v0+v1+v2
然 后 就 要 构 造 边 的 容 量 了 。 然后就要构造边的容量了。 然后就要构造边的容量了。
b
和
d
分
别
是
连
向
汇
点
的
边
,
则
为
w
x
+
v
0
2
和
w
y
+
v
0
2
。
b和d分别是连向汇点的边,则为w_x+\frac{v_0}{2}和w_y+\frac{v_0}{2}。
b和d分别是连向汇点的边,则为wx+2v0和wy+2v0。
a
和
c
分
别
是
连
向
源
点
的
边
,
则
为
v
1
2
和
v
1
2
a和c分别是连向源点的边,则为\frac{v_1}{2}和\frac{v_1}{2}
a和c分别是连向源点的边,则为2v1和2v1
剩
下
的
e
和
f
解
出
来
为
v
2
+
v
0
+
v
1
2
剩下的e和f解出来为v_2+\frac{v_0+v_1}{2}
剩下的e和f解出来为v2+2v0+v1
Code
#include "bits/stdc++.h"
using namespace std;
struct Dinic {
static const int N = 1e3 + 10, M = 1e5 + 10, INF 0x3f3f3f3f;
int n, m, s, t;
int maxflow;
int deep[N], cur[N];
struct Edge {
int v, next;
int cap;
}e[M << 1];
int head[M << 1], cnt;
void init() {
memset(head, -1, sizeof head);
cnt = maxflow = 0;
}
void add(int u, int v, int cap) {
e[cnt].v = v;
e[cnt].cap = cap;
e[cnt].next = head[u];
head[u] = cnt++;
e[cnt].v = u;
e[cnt].cap = 0;
e[cnt].next = head[v];
head[v] = cnt++;
}
bool bfs() {
for(int i = 0;i <= t; i++) {
deep[i] = -1, cur[i] = head[i];
}
queue<int> q;
q.push(s); deep[s] = 0;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(deep[v] == -1 && e[i].cap) {
deep[v] = deep[u] + 1;
q.push(v);
}
}
}
if(deep[t] >= 0) return true;
else return false;
}
int dfs(int u, int mx) {
int a;
if(u == t) return mx;
for(int i = cur[u]; ~i; i = e[i].next) {
cur[u] = i;
int v = e[i].v;
if(e[i].cap && deep[v] == deep[u] + 1 && (a = dfs(v, min(mx, e[i].cap)))) {
e[i].cap -= a;
e[i ^ 1].cap += a;
return a;
}
}
return 0;
}
void dinic() {
while(bfs()) {
while(1) {
int res = dfs(s, INF);
if(!res) break;
maxflow += res;
}
}
}
}mf;
void solve() {
int n, q; cin >> n >> q;
mf.init();
int ans = 0;
mf.n = n; mf.s = 0; mf.t = n + 1;
vector<int> w(n + 1), m(n + 1);
for(int i = 1;i <= n; i++) cin >> w[i], ans += w[i];
for(int i = 1;i <= q; i++) {
int x, y, v0, v1, v2; cin >> x >> y >> v0 >> v1 >> v2;
ans += v0 + v1;
w[x] += v0 / 2; w[y] += v0 / 2;
m[x] += v1 / 2; m[y] += v1 / 2;
mf.add(x, y, v2 + (v0 + v1) / 2);
mf.add(y, x, v2 + (v0 + v1) / 2);
}
for(int i = 1;i <= n; i++) {
mf.add(mf.s, i, m[i]);
mf.add(i, mf.t, w[i]);
}
mf.dinic();
cout << ans - mf.maxflow << endl;
}
signed main() {
solve();
}