链接:
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;
}