最大权闭合子图
学习链接
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;
}
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~