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年杭电多校第九场07题(HDU6686+树形dp)

2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

2019杭电多校第二场hdu6602 Longest Subarray(线段树)

2020杭电多校第二场

2018杭电多校第二场1003(DFS,欧拉回路)

2020杭电多校第二场题解