@description@

n 个士兵,每个士兵可以选择加入 A 组或 B 组。

有 m 个组合技可以增加整个军队的力量:第 i 个组合技涉及到士兵 ui 与 vi,当两人同时加入 A 组力量值增加 ai,同时加入 B 组力量值增加 ci,否则力量值增加 bi。

求每种安排士兵的方案中军队的力量值最大可以为多少。

Input

多组数据。

每组数据开头包含两个正整数 n(n≤500) 和 m(m≤10^4)。

接下来 m 行,每行包含 5 个整数 u,v,a,b,c(1≤u,v≤n,u≠v,1≤a,b,c≤4×10^6),含义如上。保证同一对 (u, v) 只会出现一次。

保证 n 总和不超过 5×10^3,m 总和不超过 5×10^4。

Output

对于每组数据,输出最大力量值。

Sample Input

3 2

1 2 8 3 3

2 3 4 3 6

Sample Output

12

@solution@

这道题这么多年过去。。。怕不是已经成了套路题。。。

【注:因为我懒所以本来下面应该有讲解的图,但是被我咕了】

我们考虑使用最小割,用所有收益的总和 - 最小割代表的最小代价。

考虑建图:s 向 x 连边,x 向 t 连边。如果割前一条表示选择 A 组,割后一条表示选择 B 组。

考虑 m 对关系,我们先设 (s, u) 容量为 e,(s, v) 容量为 f;(u, t) 容量为 g,(v, t) 容量为 h;(u, v) 容量为 p,(v, u) 容量为 q。

则接下来我们分类讨论 u, v 的选择情况,求出其应该舍弃的收益(即代价)与应该割的边的对应关系。

u 选 A 组,v 选 A 组:对应割 (s, u), (s, v);其代价为 b + c;其对应的边容量和为 e + f。

u 选 B 组,v 选 B 组:对应割 (u, t), (v, t);其代价为 a + b;其对应的边容量和为 g + h。

u 选 A 组,v 选 B 组:对应割 (s, u), (v, t), (v, u);其代价为 a + c;其对应的边容量和为 e + h + q。

u 选 B 组,v 选 A 组:对应割 (u, t), (s, v), (u, v);其代价为 a + c;其对应的边容量和为 g + f + p。

由上,可以得到 e + f = b + c 等方程。注意到只有 a, b, c 为常量,所以这个方程可能有很多解。

在此处,我们仅考虑一组特殊解,即令 p = q, e = f, g = h。此时可以解出 e = f = (b + c) / 2, g = h = (a + b) / 2, p = q = (a + c) / 2 - b。

于是,我们可以对于每个 x 统计与 x 有关的组合技中 (b + c) / 2 之和与 (a + b) / 2 之和(分别记为 s1[x], s2[x]),然后 s 向 x 连容量为 s1[x] 的边,x 向 t 连容量为 s2[x] 的边。

两个点之间如果有组合技,则连一条双向的、容量为 (a + c) / 2 - b 的边。

这样跑最小割就可以跑出最小代价。除以 2 什么的可以把所有容量乘 2 再最后除回来。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF = (1LL<<60);
const int MAXN = 500;
const int MAXM = 10000;
const int MAXV = MAXN;
const int MAXE = 4*(MAXN + MAXM);
struct FlowGraph{
struct edge{
int to; ll cap, flow;
edge *nxt, *rev;
}edges[MAXE + 5], *adj[MAXV + 5], *ecnt;
int d[MAXV + 5], vd[MAXV + 5], s, t;
void init(int n) {
for(int i=1;i<=n;i++)
d[i] = vd[i] = 0, adj[i] = NULL;
ecnt = &edges[0];
}
void addedge(int u, int v, ll c) {
edge *p = (++ecnt), *q = (++ecnt);
p->to = v, p->cap = c, p->flow = 0;
p->nxt = adj[u], adj[u] = p;
q->to = u, q->cap = 0, q->flow = 0;
q->nxt = adj[v], adj[v] = q;
p->rev = q, q->rev = p;
}
ll aug(int x, ll tot) {
if( x == t ) return tot;
int mind = t + 1; ll sum = 0;
for(edge *p=adj[x];p;p=p->nxt) {
if( p->cap > p->flow ) {
if( d[p->to] + 1 == d[x] ) {
ll del = aug(p->to, min(tot - sum, p->cap - p->flow));
sum += del, p->flow += del, p->rev->flow -= del;
if( sum == tot || d[s] == t + 1 ) return sum;
}
mind = min(mind, d[p->to]);
}
}
if( sum == 0 ) {
vd[d[x]]--;
if( vd[d[x]] == 0 ) {
d[s] = t + 1;
return sum;
}
d[x] = mind + 1;
vd[d[x]]++;
}
return sum;
}
ll max_flow(int _s, int _t) {
s = _s, t = _t;
ll flow = 0;
while( d[s] != t + 1 )
flow += aug(s, INF);
return flow;
}
}G;
ll x[MAXN + 5], y[MAXN + 5];
int main() {
int n, m;
while( scanf("%d%d", &n, &m) == 2 ) {
G.init(n + 2);
for(int i=1;i<=n;i++)
x[i] = y[i] = 0;
ll ans = 0;
int s = n + 1, t = n + 2;
for(int i=1;i<=m;i++) {
int u, v, a, b, c;
scanf("%d%d%d%d%d", &u, &v, &a, &b, &c);
x[u] += a + b, x[v] += a + b;
y[u] += c + b, y[v] += c + b;
G.addedge(u, v, a + c - 2*b);
G.addedge(v, u, a + c - 2*b);
ans += a + b + c;
}
for(int i=1;i<=n;i++)
G.addedge(s, i, x[i]), G.addedge(i, t, y[i]);
printf("%lld\n", ans - G.max_flow(s, t)/2);
}
}

@details@

不要问我为什么即使用了 long long 还是跑得非常快,问就是 O(能过)。

原题目还给了 a, b, c 之间种种不可描述的关系。。。但其实也是用来迷惑人的。。。

@hdu - 6598@ Harmonious Army的更多相关文章

  1. Hdu 6598 Harmonious Army 最小割

    N个人 每个人可以是战士/法师  M个组合 每个组合两个人 同是战士+a 同是法师+c 否则+b 对于每一个u,v,a,b,c 建(S,u,a) (u,v,a+c-2*b) (v,T,c) (S,v, ...

  2. 2019HDU多校赛第二场 H HDU 6598 Harmonious Army(最小割模型)

    参考博客https://blog.csdn.net/u013534123/article/details/97142191 #include<bits/stdc++.h> using na ...

  3. 2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型

    题意: 有n个士兵,你可以选择让它成为战士还是法师. 有m对关系,u和v 如果同时为战士那么你可以获得a的权值 如果同时为法师,你可以获得c的权值, 如果一个为战士一个是法师,你可以获得b的权值 问你 ...

  4. 题解:HDU 6598

    题解:HDU 6598 Description Now, Bob is playing an interesting game in which he is a general of a harmon ...

  5. Harmonious Army

    Harmonious Army Now, Bob is playing an interesting game in which he is a general of a harmonious arm ...

  6. hdu多校第二场1008(hdu6598) Harmonious Army 最小割

    题意: 一个军队有n人,你可以给他们每个人安排战士或者法师的职业,有m对人有组合技,组合技的信息是a,b,c,代表如果这两个人是两个战士,则组合技威力为a,一个战士一个法师,威力为b,其中b=a/4+ ...

  7. [2019杭电多校第二场][hdu6598]Harmonious Army(最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6598 题意是说一个军队有n人,你可以给他们每个人安排战士或者法师的职业,有m对人有组合技,组合技的信息 ...

  8. 2019 Multi-University Training Contest 2 - 1008 - Harmonious Army - 最大流

    http://acm.hdu.edu.cn/showproblem.php?pid=6598 一开始就觉得是网络流,但是一直都不会怎么建图. 这里要考虑. 每一组边(u,v,a,b,c)建立如下的连接 ...

  9. HDU 3970 Harmonious Set 容斥欧拉函数

    pid=3970">链接 题解:www.cygmasot.com/index.php/2015/08/17/hdu_3970 给定n  求连续整数[0,n), 中随意选一些数使得选出的 ...

随机推荐

  1. 前端js框架引入管理bundle.js

    最先在ionic中看到bundle.js,,,然而它不是一个框架

  2. day38 10-Spring的Bean的属性的注入

    后处理bean,如果是返回bean,那么什么都不做直接把这个类原封不动地给你返回回去. 在它执行一些逻辑方法的时候对它进行逻辑增强,比如说进行时间监控,权限管理,日志的记录等等. 要做肯定是对正常的类 ...

  3. 洛谷P1968 美元汇率[2017年4月计划 动态规划02]

    P1968 美元汇率 题目背景 此处省略maxint+1个数 题目描述 在以后的若干天里戴维将学习美元与德国马克的汇率.编写程序帮助戴维何时应买或卖马克或美元,使他从100美元开始,最后能获得最高可能 ...

  4. 模拟19 题解(waiting)

    T1,千万别转化成链了!! 直接数就可以,dfs搜索每种情况,对于搜到的点,如果子树大小过大,直接return,相等说明可以,小的话向上累加, 优化是先预处理子树大小,若子树小,不用搜了直接加上就行 ...

  5. 【JZOJ4161】于神之怒 莫比乌斯反演

    任务 答案mod 1e9+7. 解法 容易写出反演: Ans=∑T=1nTk∗∑i=1⌊nT⌋⌊niT⌋⌊miT⌋μ(i) ∑⌊nT⌋i=1⌊niT⌋⌊miT⌋μ(i)这个因式显然是经典的分块处理: ...

  6. 为什么DW的可视化下看到的效果与浏览器的效果有所区别?

    可视区不是调用外面浏览器,Dreamweav 可视化区是为用户编辑而设计. 支持最基本的 HTML 与 CSS ,对 CSS 而言,我写入样式时如果你使用最基本的样式时它显示与你浏览器中看的效果相差不 ...

  7. tes..

    力扣刷题 二分查找法 二分查找法又称折半查找法. 优点:比较次数少,查找速度快,平均性能好: 缺点:要求待查表为有序表,且插入删除困难. 因此,折半查找方法适用于不经常变动而查找频繁的有序列表. 首先 ...

  8. 批量删除maven lastUpdated

    批量删除lastUpdated for /r %i in (*.lastUpdated) do del %i 安装jar到本地仓库 mvn install:install-file -Dfile=D: ...

  9. NOIP模拟 7.04

    魔术球问题弱化版(ball.c/.cpp/.pas) [题目描述] 假设有 n 根柱子,现要按下述规则在这 n 根柱子中依次放入编号为 1,2,3,…的球. (1)每次只能在某根柱子的最上面放球. ( ...

  10. mysql更改密码

    mysql command line client输入密码以后闪退问题的解决: 网上搜到的解决办法(my.ini文件之类的修改对我都没有起到作用).. 所以觉得是自己密码的问题,因为许久不用这个软件了 ...