zoukankan      html  css  js  c++  java
  • 2019 Petrozavodsk Winter Camp, Yandex Cup C. Diverse Singing 上下界网络流

    建图一共建四层 第一层为N个歌手 第二层为{pi,li} 第三层为{si,li} 第四层为M首歌

    除了S和第一层与第三层与T之间的边为[1,INF] 其他边均为[0,1]

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef int JQK;
    const JQK INF = 1000000005;
    struct node {
            int p, s, l;
            bool operator <(const node &rhs) const {
                    if (p != rhs.p)
                            return p > rhs.p;
                    else {
                            if (s != rhs.s)
                                    return s > rhs.s;
                            else
                                    return l > rhs.l;
                    }
            }
    } nodecnt;
    int n, m, k, s1, t1, s2, t2;
    map<pair<int, int>, int> pl, sl;
    map<int, pair<int, int> > plb, slb;
    map<node, int> psl;
    vector<int> anser;
    namespace dinic {
            const int MAXN = 30050;
            const int MAXM = 100050;
            const JQK INF = 1000000050;
            int Head[MAXN], cur[MAXN], lev[MAXN], to[MAXM << 1], nxt[MAXM << 1], ed = 1;
            int S, T, SS, TT, MAXP;
            JQK f[MAXM << 1], totflow[MAXN];
            inline void addedge(int u, int v, JQK cap) {
                    to[++ed] = v;
                    nxt[ed] = Head[u];
                    Head[u] = ed;
                    f[ed] = cap;
                    to[++ed] = u;
                    nxt[ed] = Head[v];
                    Head[v] = ed;
                    f[ed] = 0;
                    return;
            }
            inline void add(int u, int v, JQK caplow, JQK captop) {
                    addedge(u, v, captop - caplow);
                    totflow[u] -= caplow, totflow[v] += caplow;
                    return ;
            }
            inline bool BFS() {
                    int u;
                    for (int i = 0; i <= MAXP + 1; i++) {
                            lev[i] = -1;
                    }
                    //memset(lev, -1, sizeof(lev));
                    queue<int>q;
                    lev[S] = 0;
                    q.push(S);
                    while (q.size()) {
                            u = q.front();
                            q.pop();
                            for (int i = Head[u]; i; i = nxt[i])
                                    if (f[i] && lev[to[i]] == -1) {
                                            lev[to[i]] = lev[u] + 1;
                                            q.push(to[i]);
                                            /*
                                            if (to[i] == T)
                                            {
                                                    return 1;
                                            }
                                            magic one way optimize
                                            */
                                    }
                    }
                    for (int i = 0; i <= MAXP + 1; i++) {
                            cur[i] = Head[i];
                    }
                    //memcpy(cur, Head, sizeof Head);
                    return lev[T] != -1;
            }
            inline JQK DFS(int u, JQK maxf) {
                    if (u == T || !maxf) {
                            return maxf;
                    }
                    JQK cnt = 0, tem;
                    for (int &i = cur[u]; i; i = nxt[i])
                            if (f[i] && lev[to[i]] == lev[u] + 1) {
                                    tem = DFS(to[i], min(maxf, f[i]));
                                    maxf -= tem;
                                    f[i] -= tem;
                                    f[i ^ 1] += tem;
                                    cnt += tem;
                                    if (!maxf) {
                                            break;
                                    }
                            }
                    if (!cnt) {
                            lev[u] = -1;
                    }
                    return cnt;
            }
            JQK Dinic() {
                    JQK ans = 0;
                    while (BFS()) {
                            ans += DFS(S, INF);
                    }
                    return ans;
            }
            void del(int x) {
                    for (int i = Head[x]; i; i = nxt[i])
                            f[i] = f[i ^ 1] = 0;
            }
            void init(int S1, int T1, int S2, int T2) {
                    for (int i = 0; i <= MAXP + 1; i++) {
                            totflow[i] = Head[i] = 0;
                    }
                    ed = 1;
                    S = S1;
                    T = T1;
                    SS = S2;
                    TT = T2;
                    return;
            }
            inline JQK pushdownflow(int x) {
                    JQK sum = 0;
                    for (int i = 1; i <= x; i++) {
                            if (totflow[i] > 0) {
                                    addedge(SS, i, totflow[i]);
                                    sum += totflow[i];
                            } else if (totflow[i] < 0) {
                                    addedge(i, TT, -totflow[i]);
                            }
                    }
                    return sum;//sum==dinic 循环流有解
            }
            JQK work() { //有源汇最大流
                    JQK ans = 0;
                    JQK sum = pushdownflow(TT - 2);
                    addedge(T, S, INF);
                    swap(S, SS), swap(T, TT);
                    if (sum != Dinic()) { //Dinic(SS,TT) 求出一个有源汇有上下界可行流.此时的流不一定最大.
                            cout << -1 << endl;
                            return 0;
                    }
                    ans = f[ed]; //可行流流量
                    f[ed] = f[ed ^ 1] = 0;
                    swap(S, SS), swap(T, TT); //Dinic(S,T)
                    ans += Dinic();//新增广出的s-t流量
                    cout << ans << endl;
                    for (int i = n + m + 1; i <= n + m + k; i++) {
                            for (int j = Head[i]; j; j = nxt[j]) {
                                    int v = to[j];
                                    if (v >= n + m + k + 1 && v <= n + m + 2 * k && f[j] == 0) {
                                            nodecnt.p = plb[i].first;
                                            nodecnt.s = slb[v].first;
                                            nodecnt.l = slb[v].second;
                                            anser.push_back(psl[nodecnt]);
                                    }
                            }
                    }
                    sort(anser.begin(), anser.end());
                    for (int v : anser) {
                            cout << v << " ";
                    }
                    return ans;
            }
    }
    int main() {
            int u, v;
            JQK c;
            scanf("%d %d %d", &n, &m, &k);
            dinic::MAXP = n + m + 2 * k + 5;
            s1 = n + m + 2 * k + 1;
            t1 = s1 + 1;
            s2 = t1 + 1;
            t2 = s2 + 1;
            dinic::init(s1, t1, s2, t2); //S T SS TT
            for (int i = 1; i <= n; i++)
                    dinic::add(s1, i, 1, INF);
            for (int i = n + 1; i <= n + m; i++)
                    dinic::add(i, t1, 1, INF);
            for (int i = 1; i <= k; i++) {
                    scanf("%d %d %d", &u, &v, &c);
                    nodecnt.p = u, nodecnt.s = v, nodecnt.l = c;
                    if (!psl[nodecnt])
                            psl[nodecnt] = i;
                    if (!pl[make_pair(u, c)]) {
                            pl[make_pair(u, c)] = n + m + i;
                            plb[n + m + i] = make_pair(u, c);
                            dinic::add(u, n + m + i, 0, 1);
                    }
                    if (!sl[make_pair(v, c)]) {
                            sl[make_pair(v, c)] = n + m + k + i;
                            slb[n + m + k + i] = make_pair(v, c);
                            dinic::add(n + m + k + i, n + v, 0, 1);
                    }
                    dinic::add(pl[make_pair(u, c)], sl[make_pair(v, c)], 0, 1);
            }
            dinic::work();
            return 0;
    }
  • 相关阅读:
    阿里P8推荐的SpingBoot学习手册+Git开源项目实践分享,还不收藏
    阿里P8划重点:JVM+Spring+Mybatis+多线程高并发源码你必须会
    一线大厂工程师推荐:Mysql、Springboot、JVM、Spring等面试合集
    GitHub标星120K+的JDK并发编程指南,连续霸榜GitHub终于开源了
    腾讯被指劝退高龄员工,华为百度也在优化,互联网35岁+该怎么办
    天猫面试官硬核推荐:Dubbo+ES+JVM+多线程/高并发+消息队列
    多线程与高并发:金九银十跳槽季面试必须要掌握的硬核涨薪技能
    纯干货,源码6步曲,带你解析完整的ThreadPoolExecutor
    今日总结
    今日头条技术架构分析
  • 原文地址:https://www.cnblogs.com/Aragaki/p/11590378.html
Copyright © 2011-2022 走看看