[POJ 2987]每个人都为公司带来一个收益,公司老板要裁员(当然是业绩不好给公司带来负收益的人被裁掉啦~),然而踢走一个人会把他的下属都踢走,求最大收益
最大权闭合子图~,其实就是最小割啦,此题要求最小化走的人数,然而就是最小割中的人数QAQ(并不知道为什么),dfs(S)相关的点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 100010
using namespace std;
typedef long long ll;
const int inf = 0x7fffffff;
int n, m;
struct Edge{
int to, next, w;
Edge(int v = 0, int nxt = 0, int d = 0){
to = v, next = nxt, w = d;
}
}edge[maxn * 5];
int h[maxn], cnt = 1, S, T;
void add(int u, int v, int w){
edge[++ cnt] = Edge(v, h[u], w); h[u] = cnt;
edge[++ cnt] = Edge(u, h[v], 0); h[v] = cnt;
}
queue<int> Q;
int d[70000];
bool BFS(){
memset(d, -1, sizeof d);
d[S] = 0; Q.push(S);
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = h[u]; i; i = edge[i].next){
if(!edge[i].w)continue;
int v = edge[i].to;
if(d[v] == -1) d[v] = d[u] + 1, Q.push(v);
}
}return d[T] != -1;
}
int cur[maxn];
ll DFS(int x, ll a){
if(x == T || a == 0)
return a;
int used = 0, f;
for(int i = cur[x]; i; i = edge[i].next){
int v = edge[i].to;
if(d[v] == d[x] + 1 && edge[i].w){
f = DFS(v, min(a-used, (ll)edge[i].w));
edge[i].w -= f;
edge[i^1].w += f;
used += f;
if(f > 0)cur[x] = i;
if( used == a)return used;
}
}
if(used == 0)d[x] = -1;
return used;
}
ll Dinic(){
ll ret = 0;
while(BFS()){
for(int i = S; i <= T; i ++)
cur[i] = h[i];
ret += DFS(S, inf);
}
return ret ;
}
bool vis[maxn];
void dfs(int u){
vis[u] = true;
for(int i = h[u]; i; i = edge[i].next){
int v = edge[i].to;
if(edge[i].w && !vis[v])
dfs(v);
}
}
int main(){
scanf("%d%d", &n, &m);
S = 0, T = n + m + 1;
int b;
ll sum = 0;
for(int i = 1; i <= n; i ++){
scanf("%d", &b);
if(b > 0){
add(S, i, b);
sum += b;
}
else add(i, T, -b);
}
int u, v;
for(int i = 1; i <= m; i ++){
scanf("%d%d", &u, &v);
add(u, v, inf);
}
sum -= Dinic();
dfs(S);
int ans = 0;
for(int i = 1; i <= n; i ++)
ans += vis[i];
printf("%d %lld\n", ans, sum);
return 0;
}
[HDU 3879]建立一个新站点需要Pi的花费,给定m个客户使用两个站点所带来的收益Ci,最大化收益
把每一个客户新建一个点然后建图QAQ,不能在原图上直接连边。。只贴建图了QAQ。。
while(scanf("%d%d", &n, &m) == 2){
memset(h, 0, sizeof h); cnt = 1;
int p; S = 0, T = n + m + 1;
for(int i = 1; i <= n; i ++){
scanf("%d", &p);
add(S, i, p);
}
int u, v, w, sum = 0, size = n;
for(int i = 1; i <= m; i ++){
scanf("%d%d%d", &u, &v, &w);
++ size;
add(u, size, inf);
add(v, size, inf);
add(size, T, w);
sum += w;
}
printf("%d\n", sum - Dinic());
}
[HDU 4971]
The first line of the input is a single integer T(<=100) which is the number of test cases.
Each test case contains a line with two integer n(<=20) and m(<=50) which is the number of project to select to complete and the number of technical problem.
Then a line with n integers. The i-th integer(<=1000) means the profit of complete the i-th project.
Then a line with m integers. The i-th integer(<=1000) means the cost of training to solve the i-th technical problem.
Then n lines. Each line contains some integers. The first integer k is the number of technical problems, followed by k integers implying the technical problems need to solve for the i-th project.
After that, there are m lines with each line contains m integers. If the i-th row of the j-th column is 1, it means that you need to solve the i-th problem before solve the j-th problem. Otherwise the i-th row of the j-th column is 0.
就是有问题和工程,解决问题是有关联性的而且要花费代价,解决一些问题可以去做某工程带来一些收益,求最大化收益
最重要的是建图啦。。
for(int dir = 1; dir <= test; dir ++){
memset(h, 0, sizeof h);
int sum = 0, p, k;
scanf("%d%d", &n, &m);
cnt = 1, S = 0, T = n + m + 1;
for(int i = 1; i <= n; i ++){
scanf("%d", &p);
add(S, i, p);
sum += p;
}
for(int i = 1; i <= m; i ++){
scanf("%d", &p);
add(i + n, T, p);
}
for(int i = 1; i <= n; i ++){
scanf("%d", &k);
for(int j = 1; j <= k; j ++){
scanf("%d", &p); p ++;
add(i, p + n, inf);
}
}
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= m; j ++){
scanf("%d", &p);
if(p == 1) add(i + n, j + n, inf);
}
}
printf("Case #%d: %d\n", dir, sum - Dinic());
}