poj2987最大权闭包(输出最少建塔个数)
生活随笔
收集整理的這篇文章主要介紹了
poj2987最大权闭包(输出最少建塔个数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ?公司要裁員,每個員工被裁掉之后都會有一定的收益(正或者負),有一些員工之間有限制關系,就是裁掉誰之前必須要先裁掉另一個人,問公司的最大收益和最大收益前提下的最小裁員人數?
思路:
? ? ?公司要裁員,每個員工被裁掉之后都會有一定的收益(正或者負),有一些員工之間有限制關系,就是裁掉誰之前必須要先裁掉另一個人,問公司的最大收益和最大收益前提下的最小裁員人數?
思路:
? ? ? 收益有正、有負,員工之間有限制關系,那么是不是瞬間就想到了杭電的那個通訊塔的那么題目,雖然那個是最大點權獨立集,而這二個是最大權閉包,但是我感覺兩者想法一樣,只不過中間是通過一些轉換了,這個題有個特別的地方,就是輸出最小裁員人數,這個還真不知道怎么弄,然后在網上看了下,說是在殘余網絡上直接從起點開始搜索,能走到幾個就是幾,寫到是很好寫,關鍵是理解為什么?這個據說論文上有,我說下我的理解,我感覺可能是這樣,ss-a-b-tt,如果跑完之后ss-a還有流量會怎樣?是不是還有流量就證明掙的錢比花的錢多,那么我們就刪除點a,b就行了,把問題復雜化也一樣,ss-a-b-tt ss-a-c-tt ,就是說刪除a之前要刪除b,c才行,如果ss-a還有流量就證明ss-a > (b->tt)+(c->tt)那么刪除他們三個是最優的......
#include<queue> #include<stdio.h> #include<string.h>#define N_node 5500 #define N_edge 150000 #define INF 0x3f3f3f3f3f3f3f3fusing namespace std;typedef struct {int to ,next;long long cost; }STAR;typedef struct {int x ,t; }DEP;DEP xin ,tou; STAR E[N_edge]; int list[N_node] ,listt[N_node] ,tot; int deep[N_node];void add(int a ,int b ,long long c) {E[++tot].to = b;E[tot].cost = c;E[tot].next = list[a];list[a] = tot;E[++tot].to = a;E[tot].cost = 0;E[tot].next = list[b];list[b] = tot; }long long minn(long long x ,long long y) {return x < y ? x : y; }bool BFS_Deep(int s ,int t ,int n) {memset(deep ,255 ,sizeof(deep));xin.x = s ,xin.t = 0;deep[xin.x] = xin.t;queue<DEP>q;q.push(xin);while(!q.empty()){tou = q.front();q.pop();for(int k = list[tou.x] ;k ;k = E[k].next){xin.x = E[k].to;xin.t = tou.t + 1;if(deep[xin.x] != -1 || !E[k].cost)continue;deep[xin.x] = xin.t;q.push(xin);}}for(int i = 0 ;i <= n ;i ++)listt[i] = list[i];return deep[t] != -1; }long long DFS_Flow(int s ,int t ,long long flow) {if(s == t) return flow;long long nowflow = 0;for(int k = listt[s] ;k ;k = E[k].next){listt[s] = k;int to = E[k].to;long long c = E[k].cost;if(deep[to] != deep[s] + 1 || !c)continue;long long tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));nowflow += tmp;E[k].cost -= tmp;E[k^1].cost += tmp;if(nowflow == flow) break;}if(!nowflow) deep[s] = 0;return nowflow; }long long DINIC(int s ,int t ,int n) {long long Ans = 0;while(BFS_Deep(s ,t ,n)){Ans += DFS_Flow(s ,t ,INF);}return Ans; }int SS; int mark[N_node]; void DFS(int s) {mark[s] = 1;for(int k = list[s] ;k ;k = E[k].next){if(!mark[E[k].to] && E[k].cost){SS ++;DFS(E[k].to);}}return ; }int main () {int n ,m ,i ,a ,b;long long c ,S;while(~scanf("%d %d" ,&n ,&m)){int ss = 0 ,tt = n + 1;memset(list ,0 ,sizeof(list));tot = 1;for(S = 0 ,i = 1 ;i <= n ;i ++){scanf("%lld" ,&c);c > 0 ? add(ss ,i ,c) : add(i ,tt ,-c);if(c > 0) S += c;}for(i = 1 ;i <= m ;i ++){scanf("%d %d" ,&a ,&b);add(a ,b ,INF);}S -= DINIC(ss ,tt ,tt);memset(mark ,0 ,sizeof(mark));SS = 0;DFS(ss);printf("%d %lld\n" ,SS ,S);}return 0; }
總結
以上是生活随笔為你收集整理的poj2987最大权闭包(输出最少建塔个数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ2528线段树段更新逆序异或(广告
- 下一篇: POJ2752KMP逆序处理