题意:

有n个士兵,你可以选择让它成为战士还是法师。

有m对关系,u和v 如果同时为战士那么你可以获得a的权值

如果同时为法师,你可以获得c的权值,

如果一个为战士一个是法师,你可以获得b的权值

问你可以获得的最大权值是多少?

题解:

对每个士兵建立一个点x ,点x 向源点s 连一条边,向汇点t 连一条边,

分别表示选择两种职业,然后就可以先加上所有的贡献,通过两点关系用 最小割建模,如下图所示

设一条边的三种贡献为A, B, C,可以得到以下方程:

如果x,y都是法师,你可以获得C的权值,但是我们构建的是最小割模型(这个权值C应该是A+B+C-该图的最小割),

我们选择x,y都是法师的最小割对应的权值应该是A+B,对应的边根据上述是a,b

所以有a+b=A+B

同理对于都是战士有公式c+d=B+C

对于一战士一法师有公式a+e+d=A+C   b+e+c=A+C

存在一组解

a=b=(A+B)/2,c=d=(C+B)/2,e=-B+(A+C)/2;

为了消除浮点数的问题,我们建边的时候将边权*2,取答案的时候/2即可

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sfi(a) scanf("%d", &a)
#define sffi(a, b) scanf("%d %d", &a, &b)
#define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define sfL(a) scanf("%lld", &a)
#define sffL(a, b) scanf("%lld %lld", &a, &b)
#define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c)
#define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
#define sfs(a) scanf("%s", a)
#define sffs(a, b) scanf("%s %s", a, b)
#define sfffs(a, b, c) scanf("%s %s %s", a, b, c)
#define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
#define FIN freopen("../in.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const ULL seed = ;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = + ;
const int maxm = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int n, m; struct MaxFlow {
struct Edge {
int v, nxt;
LL w;
} edge[maxm];
int tot, num, s, t;
int head[maxn]; void init() {
memset(head, -, sizeof(head));
tot = ;
} void add(int u, int v, LL w) {
edge[tot] = (Edge) {
v, head[u], w
};
head[u] = tot++;
edge[tot] = (Edge) {
u, head[v],
};
head[v] = tot++;
} int d[maxn], vis[maxn], gap[maxn]; void bfs() {
memset(d, , sizeof(d));
memset(gap, , sizeof(gap));
memset(vis, , sizeof(vis));
queue<int> q;
q.push(t);
vis[t] = ;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if (!vis[v]) {
d[v] = d[u] + ;
gap[d[v]]++;
q.push(v);
vis[v] = ;
}
}
}
} int last[maxn]; LL dfs(int u, LL f) {
if (u == t) return f;
LL sap = ;
for (int i = last[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if (edge[i].w > && d[u] == d[v] + ) {
last[u] = i;
LL tmp = dfs(v, min(f - sap, edge[i].w));
edge[i].w -= tmp;
edge[i ^ ].w += tmp;
sap += tmp;
if (sap == f) return sap;
}
}
if (d[s] >= num) return sap;
if (!(--gap[d[u]])) d[s] = num;
++gap[++d[u]];
last[u] = head[u];
return sap;
} LL solve(int st, int ed, int n) {
LL flow = ;
num = n;
s = st;
t = ed;
bfs();
memcpy(last, head, sizeof(head));
while (d[s] < num) flow += dfs(s, INFLL);
return flow;
}
} F; int main() {
//FIN;
while (~sffi(n, m)) {
F.init();
LL sum = ;
for (int i = , u, v, a, b, c; i < m; ++i) {
sffi(u, v);
sfffi(a, b, c);
F.add(, u, a + b);
F.add(, v, a + b);
F.add(u, n + , b + c);
F.add(v, n + , b + c);
F.add(u, v, - * b + a + c);
F.add(v, u, - * b + a + c);
sum += a + b + c;
}
printf("%lld\n", ( * sum - F.solve(, n + , n + )) / );
}
return ;
}

2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型的更多相关文章

  1. 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)

    题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...

  2. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

  3. SCNU省选校赛第二场B题题解

    今晚的校赛又告一段落啦,终于"开斋"了! AC了两题,还算是满意的,英语还是硬伤. 来看题目吧! B. Array time limit per test 2 seconds me ...

  4. 2015 多校赛 第二场 1006 (hdu 5305)

    Problem Description There are n people and m pairs of friends. For every pair of friends, they can c ...

  5. 2015 多校赛 第二场 1004 hdu(5303)

    Problem Description There are n apple trees planted along a cyclic road, which is L metres long. You ...

  6. 2015 多校赛 第二场 1002 (hdu 5301)

    Description Your current task is to make a ground plan for a residential building located in HZXJHS. ...

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

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

  8. HDU 多校对抗赛第二场 1004 Game

    Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. HDU 多校对抗赛第二场 1010 Swaps and Inversions

    Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

随机推荐

  1. python 中的内置高级函数

    1.map(function,iterable) map是把迭代对象依次进行函数运算,并返回. 例子: map返回的十分map对象,需要list()函数转化. 2.exec()函数 执行储存在字符串或 ...

  2. mongodb导入csv

    主要介绍使用自带工具mongoimport工具将 CSV 格式数据导入到 MongoDB 的详细过程. 由于官方提供了mongoimport工具,所以实际上导入 CSV 格式数据的过程非常简单,再次体 ...

  3. python 调用redis

    #!/usr/bin/env python #_*_ coding:UTF-8 _*_ import redis import pickle #普通连接 ''' db="db1" ...

  4. linux安装jrockit 1.6

    文章目录 下载 安装 配置环境变量 下载 https://download.csdn.net/download/wthn163/10631876?utm_source=bbsseo 安装 将.bin结 ...

  5. strlen、strcpy和strcmp源码

    1.不使用库函数实现strcpy #include <assert.h> char *strcpy(char *dst, const char *src) { assert((dst != ...

  6. Fedora 25技巧

    shell界面按F5插入-(波浪号,HOME) 同一个应用不同窗口切换alt + `

  7. PHPExcel导出工作蒲(多表合并)教程+详细代码解读

    最近做了一个需求,导出统计数据,因为需要同时导出多个不同的统计数据,所以不能像以往导出数据列表一样去实现这个需求,刚好空下来就记录一下(PHPExcel导出Excel多sheet合并) 一.主要使用的 ...

  8. 《代码大全2》读书笔记 Week3

    <代码大全2>第六.七章 作者在第六章中从抽象数据类型(Abstract Data Type)出发阐释类(class)的概念,给出创建类的原因以及创建高质量的常涉及的设计问题.抽象数据类型 ...

  9. 2019-9-11-.NET-Standard

    title author date CreateTime categories .NET Standard lindexi 2019-9-11 9:0:29 +0800 2019-9-11 9:0:2 ...

  10. 从零开始搭建系统1.3——Tomcat安装及配置

    首先安装jdk,手动解压JDK的压缩包,然后设置环境变量 1.卸载自带openjdk 查询OpenJDK rpm -qa|grep java 批量卸载所有名字包含jdk的已安装程序.命令行: rpm  ...