最大权闭合子图

学习链接

传送门

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("*********\n")
#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\n", 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("*********\n")
#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\n", sum - f.work());
    return 0;
}

转载于:https://www.cnblogs.com/Dillonh/p/11232837.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值