[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 ", 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 ", 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 ", dir, sum - Dinic()); }