2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)
Posted Dillonh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)相关的知识,希望对你有一定的参考价值。
题目链接
题意
有\(n\)个士兵,要你给他们分配职业。有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\frac{a}{4}+\frac{c}{3}\),要你求最大的总能力。
思路
这位大佬的博客讲的很详细,大家可以看这篇博客~
在他的基础上加了点优化:源与某个点可能会连很多条边,因此我们可以汇总起来最后一次连边,汇同理,中间的反向边我们可以不用建\(0\)的边。
代码实现如下
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 500 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int cnt1[maxn], cnt2[maxn];
int n, m, u, v, a, b, c;
struct Dinic {
queue<int> q;
int tot, s, t;
LL maxflow;
int head[maxn], d[maxn];
void init() {
tot = maxflow = 0;
memset(head, -1, sizeof(head));
}
struct edge {
int v, next;
LL w;
}ed[200007];
void add(int u, int v, LL w) {
ed[tot].v = v;
ed[tot].w = w;
ed[tot].next = head[u];
head[u] = tot++;
}
bool bfs() {
memset(d, 0, sizeof(d));
d[s] = 1;
while(!q.empty()) q.pop();
q.push(s);
int x;
while(!q.empty()) {
x = q.front();
q.pop();
for(int i = head[x]; ~i; i = ed[i].next) {
if(ed[i].w && !d[ed[i].v]) {
d[ed[i].v] = d[x] + 1;
q.push(ed[i].v);
if(ed[i].v == t) return 1;
}
}
}
return 0;
}
LL dinic(int x, LL flow) {
if(x == t) return flow;
LL res = flow, k, v;
for(int i = head[x]; ~i && res; i = ed[i].next) {
v = ed[i].v;
if(ed[i].w && d[v] == d[x] + 1) {
k = dinic(v, min(res, ed[i].w));
if(!k) d[v] = 0;
ed[i].w -= k;
ed[i^1].w += k;
res -= k;
}
}
return flow - res;
}
LL work() {
LL flow = 0;
while(bfs()) {
while(flow = dinic(s, inf)) maxflow += flow;
}
return maxflow;
}
}f;
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
while(~scanf("%d%d", &n, &m)) {
f.s = 0, f.t = n + 1;
f.init();
LL sum = 0;
for(int i = 1; i <= m; ++i) {
scanf("%d%d%d%d%d", &u, &v, &a, &b, &c);
sum += (a + b + c) * 2;
cnt1[u] += 5 * a / 4 + c / 3;
cnt1[v] += 5 * a / 4 + c / 3;
cnt2[u] += a / 4 + 4 * c / 3;
cnt2[v] += a / 4 + 4 * c / 3;
f.add(u, v, a / 2 + c / 3);
f.add(v, u, a / 2 + c / 3);
}
for(int i = 1; i <= n; ++i) {
if(cnt1[i]) f.add(f.s, i, cnt1[i]), f.add(i, f.s, 0);
if(cnt2[i]) f.add(i, f.t, cnt2[i]), f.add(f.t, i, 0);
cnt1[i] = cnt2[i] = 0;
}
printf("%lld\n", (sum - f.work()) / 2);
}
return 0;
}
以上是关于2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)的主要内容,如果未能解决你的问题,请参考以下文章
2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)