• 最大权闭合子图


    学习链接

    传送门

    hihoCoder(1398)

    思路

    将所有的活动与超级源点连起来,边权为活动的活跃值;学生与超级汇点连起来,边权为邀请学生的花费;将活动与所需要的学生连边,边权为(inf)。最后答案为所有活动的活跃值之和减去最小割。

    代码实现如下

    #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("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    #define FIN freopen("/home/dillonh/CLionProjects/Dillonh/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 = 400 + 7;
    const double pi = acos(-1);
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3fLL;
    
    
    int n, m, x, num;
    
    struct Dinic {
        queue<int> q;
        int maxflow, tot, s, t;
        int head[maxn], d[maxn];
        void init() {
            tot = maxflow = 0;
            memset(head, -1, sizeof(head));
        }
        struct edge {
            int v, w, next;
        }ed[maxn*maxn];
        void add(int u, int v, int w) {
            ed[tot].v = v;
            ed[tot].w = w;
            ed[tot].next = head[u];
            head[u] = tot++;
            ed[tot].v = u;
            ed[tot].w = 0;
            ed[tot].next = head[v];
            head[v] = 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;
        }
        int dinic(int x, int flow) {
            if(x == t) return flow;
            int 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;
        }
        int work() {
            int flow = 0;
            while(bfs()) {
                while(flow = dinic(s, inf)) maxflow += flow;
            }
            return maxflow;
        }
    }f;
    
    int main() {
    #ifndef ONLINE_JUDGE
        FIN;
    #endif
        scanf("%d%d", &n, &m);
        f.s = 0, f.t = n + m + 1;
        f.init();
        for(int i = 1; i <= m; ++i) {
            scanf("%d", &x);
            f.add(n + i, f.t, x);
        }
        int sum = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%d%d", &x, &num);
            f.add(f.s, i, x);
            sum += x;
            while(num--) {
                scanf("%d", &x);
                f.add(i, n + x, inf);
            }
        }
        printf("%d
    ", sum - f.work());
        return 0;
    }
    

    勤奋的杨老师(二)

    思路

    将智慧值的和与智力消耗值的和的差值为正的与源点连接,边权为差值,将智慧值的和与智力消耗值的和的差值为负的与汇点连接,边权为差值的绝对值,有前置技能的则将该技能与其前置技能点连边,边权为(inf),最后跑最大权闭合子图即可。

    代码实现如下

    #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("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    #define FIN freopen("/home/dillonh/CLionProjects/Dillonh/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 n, x, y, u, v;
    
    struct Dinic {
        queue<int> q;
        int maxflow, tot, s, t;
        int head[maxn], d[maxn];
        void init() {
            tot = maxflow = 0;
            memset(head, -1, sizeof(head));
        }
        struct edge {
            int v, w, next;
        }ed[maxn*maxn];
        void add(int u, int v, int w) {
            ed[tot].v = v;
            ed[tot].w = w;
            ed[tot].next = head[u];
            head[u] = tot++;
            ed[tot].v = u;
            ed[tot].w = 0;
            ed[tot].next = head[v];
            head[v] = 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;
        }
        int dinic(int x, int flow) {
            if(x == t) return flow;
            int 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;
        }
        int work() {
            int flow = 0;
            while(bfs()) {
                while(flow = dinic(s, inf)) maxflow += flow;
            }
            return maxflow;
        }
    }f;
    
    int main() {
    #ifndef ONLINE_JUDGE
        FIN;
    #endif
        scanf("%d", &n);
        f.s = 0, f.t = n + 1;
        f.init();
        int sum = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%d%d", &x, &y);
            if(x - y >= 0) f.add(f.s, i, x - y), sum += x - y;
            else f.add(i, f.t, y - x);
        }
        while(~scanf("%d%d", &u, &v)) {
            f.add(v, u, inf);
        }
        printf("%d
    ", sum - f.work());
        return 0;
    }
    
  • 相关阅读:
    Linux客户/服务器程序设计范式——阿帕奇服务器(多进程)
    Linux客户/服务器程序设计范式2——并发服务器(进程池)
    封装readn
    C++学习之路: 函数适配器
    C++学习之路: 智能指针入门
    C++学习之路: 单例模板
    C++学习之路: 左值&右值 的讨论 和 ”move“ 值传递方式
    C++学习之路: 特殊操作符->的重载
    C++学习之路: 模板函数
    C++学习之路: 时间戳 封装成类
  • 原文地址:https://www.cnblogs.com/Dillonh/p/11232837.html
Copyright © 2020-2023  润新知