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