POJ 2987 Firing (最大權閉合圖)
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 12108 | Accepted: 3666 |
Description
You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do some firings. You’re now simply too mad to give response to questions like “Don’t you think it is an even more stupid decision to have signed them?”, yet calm enough to consider the potential profit and loss from firing a good portion of them. While getting rid of an employee will save your wage and bonus expenditure on him, termination of a contract before expiration costs you funds for compensation. If you fire an employee, you also fire all his underlings and the underlings of his underlings and those underlings’ underlings’ underlings… An employee may serve in several departments and his (direct or indirect) underlings in one department may be his boss in another department. Is your firing plan ready now?
Input
The input starts with two integers n (0 < n ≤ 5000) and m (0 ≤ m ≤ 60000) on the same line. Next follows n + m lines. The first n lines of these give the net profit/loss from firing the i-th employee individually bi (|bi| ≤ 107, 1 ≤ i ≤ n). The remaining m lines each contain two integers i and j (1 ≤ i
Output
Output two integers separated by a single space: the minimum number of employees to fire to achieve the maximum profit, and the maximum profit.
Sample Input
5 5 8 -9 -20 12 -10 1 2 2 5 1 4 3 4 4 5
Sample Output
2 2
思路:
有一張圖夠了,來自:
https://www.cnblogs.com/kane0526/archive/2013/04/05/3001557.html
值得一提的是,我在DFS找點數的過程中,在殘余網絡中尋找時,限制了k(邊下標)為偶數,以表示該邊是原圖中的邊。(因為我的網絡流奇數邊是原圖的反向邊),但是WA,去掉這個限制就對了,目前不知道問題出在哪裏。
![技術分享圖片](/img/jia.gif)
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<stack> 5 #include<queue> 6 #include<map> 7 #include<set> 8 #include<cstdio> 9 #include<cstring> 10 #include<cmath> 11 #include<ctime> 12 #define fuck(x) cout<<#x<<" = "<<x<<endl; 13 #define ls (t<<1) 14 #define rs ((t<<1)+1) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 300086; 19 const ll Inf = 999999999999999; 20 const int mod = 1000000007; 21 //const double eps = 1e-6; 22 //const double pi = acos(-1); 23 int n,m,s,t; 24 int Head[5510],v[maxn],Next[maxn],cnt; 25 ll w[maxn]; 26 void init(){ 27 s=0;t=n+2; 28 memset(Head,-1,sizeof(Head)); 29 cnt=0; 30 } 31 int vis[5510],num[5510]; 32 void add(int x,int y,ll z) 33 { 34 // cout<<x<<" "<<y<<" "<<z<<endl; 35 if(x==y){return;} 36 v[cnt]=y; 37 w[cnt]=z; 38 Next[cnt]=Head[x]; 39 Head[x]=cnt++; 40 41 v[cnt]=x; 42 w[cnt]=0; 43 Next[cnt]=Head[y]; 44 Head[y]=cnt++; 45 } 46 47 bool bfs() 48 { 49 memset(vis,0,sizeof(vis)); 50 for(int i=0;i<=t;i++){ 51 num[i]=Head[i]; 52 } 53 vis[s]=1; 54 queue<int>q; 55 q.push(s); 56 int r=0; 57 while(!q.empty()){ 58 int u=q.front(); 59 q.pop(); 60 int k=Head[u]; 61 while(k!=-1){ 62 if(!vis[v[k]]&&w[k]){ 63 vis[v[k]]=vis[u]+1; 64 q.push(v[k]); 65 } 66 k=Next[k]; 67 } 68 } 69 return vis[t]; 70 } 71 72 ll dfs(int u,ll f) 73 { 74 75 if(u==t){return f;} 76 int &k=num[u]; 77 while(k!=-1){ 78 if(vis[v[k]]==vis[u]+1&&w[k]){ 79 ll d=dfs(v[k],min(f,w[k])); 80 if(d>0){ 81 w[k]-=d; 82 w[k^1]+=d; 83 // fuck(d) 84 return d; 85 } 86 } 87 k=Next[k]; 88 } 89 return 0ll; 90 } 91 ll Dinic() 92 { 93 ll ans=0; 94 while(bfs()){ 95 ll f; 96 while((f=dfs(s,Inf))>0){ 97 ans+=f; 98 } 99 } 100 return ans; 101 } 102 103 int ans2=0; 104 105 void dfst(int x) 106 { 107 ans2++; 108 vis[x]=1; 109 for(int k=Head[x];k!=-1;k=Next[k]){ 110 if(w[k]&&!vis[v[k]]){dfst(v[k]);} 111 } 112 } 113 114 int main() 115 { 116 // ios::sync_with_stdio(false); 117 // freopen("in.txt","r",stdin); 118 119 scanf("%d%d",&n,&m); 120 init(); 121 ll all=0; 122 for(int i=1;i<=n;i++){ 123 ll x; 124 scanf("%lld",&x); 125 if(x>0){all+=x;add(s,i,x);} 126 else{ 127 add(i,t,-x); 128 } 129 } 130 for(int i=1;i<=m;i++){ 131 int x,y; 132 scanf("%d%d",&x,&y); 133 add(x,y,Inf); 134 } 135 ll ans1=all-Dinic(); 136 137 memset(vis,0,sizeof(vis)); 138 139 dfst(s); 140 printf("%d %lld\n",ans2-1,ans1); 141 return 0; 142 }View Code
POJ 2987 Firing (最大權閉合圖)