@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. wpf icommand 命令接口

  2. spring JdbcTemplate在spring的ioc中使用

    package com.com.jdbctemplate; import org.springframework.context.ApplicationContext; import org.spri ...

  3. 通过inputSplit分片size控制map数目

    前言:在具体执行Hadoop程序的时候,我们要根据不同的情况来设置Map的个数.除了设置固定的每个节点上可运行的最大map个数外,我们还需要控制真正执行Map操作的任务个数. 1.如何控制实际运行的m ...

  4. Ubuntu小知识:更改主机名

    Linux主机名是在安装Linux操作系统的过程中设定的,并作为网络中的某一台主机的唯一标志,但是在安装好Linux系统后,如果想修改主机名,该怎么办呢?本文介绍基于Ubuntu Desktop 9. ...

  5. 【JZOJ5086】【GDOI2017第四轮模拟day1】数列 折半搜索

    题面 有一个长度为n 的排列,现在有一些位置的数已经模糊不清了,你只知道这个排列的逆序对个数是K,你能计算出总共有多少可能的排列吗? 对于100% 的数据,n <=10^3,K<=10^9 ...

  6. 手把手教你实现一个通用的jsonp跨域方法

    什么是jsonp JSONP(JSON with Padding)是JSON的一种"使用模式",可用于解决主流浏览器的跨域数据访问的问题.由于同源策略,一般来说位于 server1 ...

  7. onethink二级导航调用

    <ul class="nav-main">//添加tree参数 <think:nav name="nav" tree="true&q ...

  8. 并发模式与 RPS 模式之争,性能压测领域的星球大战

    本文是<如何做好性能压测>系列专题分享的第四期,该专题将从性能压测的设计.实现.执行.监控.问题定位和分析.应用场景等多个纬度对性能压测的全过程进行拆解,以帮助大家构建完整的性能压测的理论 ...

  9. ansible Ansible Galaxy ansible-playbook 安装 使用 命令 笔记 生成密钥 管控机 被管控机 wget epel源

    笔记 ansible 安装 与salt对比 相同 都是为了同时在多台机器上执行相同的命令 都是python开发 不同 agent(saltstack需要安装.ansible不需要) 配置(salt配置 ...

  10. ESP8266 支持浮点运算吗?

    ESP8266 支持浮点运算吗? 可以说支持,也可以说不支持. 说不支持的原因是因为 ESP8266 内部没有 FPU,无法使用硬件计算. 说支持的意思是可以使用软件进行浮点运算,但是会很慢很慢,如果 ...