新疆大学ACM-ICPC程序设计竞赛五月月赛 D:最大权闭合子图

链接: https://www.nowcoder.com/acm/contest/116/D
来源:牛客网

题目描述

众所周知,杨老师是一位十分勤奋的老师,他非常的热爱学习。

勤奋的他为自己罗列了一个学习清单,共有n个知识点,他可以有选择的进行学习。

每个知识点都会对应0个或1个或多个先修知识点(只有学会了先修知识点才能学习该知识点),同时每个知识点都有一个智慧值和一个智力消耗值。

杨老师希望在进行过激烈的学习之后,他的收获可以·量化为所有学过的题的智慧值的和与智力消耗值的和的差值。请问,这个值最大是多少?

输入描述:

第一行:一个整数n(n<=500)接下来n行,每行两个整数,代表第i个知识点的智慧值和智力消耗值接下来若干行,每行2个整数u, v,代表u是v的先修知识点。

输出描述:

一行,表示杨老师的收获的最大值

最大权闭合子图学习链接:https://www.cnblogs.com/TreeDream/p/5942354.html

题解:根据题意建图,点权为正则从S到该店连一条容量为点权的边,点权为负从改点连一条绝对值的边。原来2个是前驱关系的连一条容量为无穷的边。

//https://www.nowcoder.com/acm/contest/116/D
 
#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 550, INF = 0x7f7f7f7f;
 
struct Edge
{
    int from, to, cap, flow;
    Edge() {
        from = to = cap = flow = 0;
    }
    Edge(int in1, int in2, int in3, int in4) {
        from = in1, to = in2, cap = in3, flow = in4;
    }
};
struct Dinic
{
    int s, t;
    vector<Edge>edges;
    vector<int>G[maxn];
    int d[maxn];
    int cur[maxn];
    void init() {
        edges.clear();
        memset(d, -1, sizeof(d));
        memset(cur, 0, sizeof(cur));
    }
    void addedge(int from, int to, int cap) {
        edges.emplace_back(from, to, cap, 0);
        edges.emplace_back(to, from, 0, 0);
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }
    bool bfs() {
        memset(d, -1, sizeof(d));
        queue<int> que;
        que.push(s);
        d[s] = 0;
        while(!que.empty()) {
            int u = que.front();  que.pop();
            for(int i = 0;i < G[u].size();i ++) {
                Edge &e = edges[G[u][i]];
                if(d[e.to] == -1 && e.cap > e.flow) {
                    d[e.to] = d[u] + 1;
                    que.push(e.to);
                }
            }
        }
        return d[t] != -1;
    }
    int dfs(int u, int a) {
        if(u == t || a == 0) return a;
        int flow = 0, f;
        for(int &i = cur[u];i < G[u].size();i ++) {
            Edge &e = edges[G[u][i]];
            if(d[e.to] == d[u] + 1) {
                f = dfs(e.to, min(a, e.cap - e.flow) );
                if(f <= 0) continue;
                e.flow += f;
                edges[G[u][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(!a) break;
            }
        }
        if(!flow) d[u] = -2;
        return flow;
    }
    int maxflow(int s, int t) {
        this->s = s, this->t = t;
        int flow = 0;
        while(bfs()) {
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, INF);
        }
        return flow;
    }
}D;
 
int h[maxn];
int main()
{
    int n, sum = 0;
    scanf("%d", &n);
    int s = 0, t = n + 1;
    for(int x,y,i = 1;i <= n;i ++) {
        scanf("%d %d", &x, &y);
        h[i] = x - y;
        if(h[i] > 0) {
            D.addedge(s, i, h[i]);
            sum += h[i];
        } else {
            D.addedge(i, t, -h[i]);
        }
    }
    int u, v;
    while(~scanf("%d %d", &u, &v)) {
        D.addedge(v, u, INF);
    }
    printf("%d\n", sum - D.maxflow(s,t));
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_36876305/article/details/80212011
今日推荐