Language:
Firing
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 individuallybi (|bi| ≤ 107, 1 ≤ i ≤ n). The remaining m lines each contain two integers i and j (1 ≤ i, j ≤ n) meaning the i-th employee has the j-th employee as his direct underling. 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 Hint As of the situation described by the sample input, firing employees 4 and 5 will produce a net profit of 2, which is maximum.
很基础的最大权闭合图
![]() 1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<cstdio> 5 #include<climits> 6 #define MAXE 65100*2 7 #define MAXP 5100 8 #define Max(a,b) a>b?a:b 9 #define Min(a,b) a<b?a:b 10 using namespace std; 11 struct Edge 12 { 13 long long int s,t,next; 14 long long f; 15 } edge[MAXE]; 16 long long int head[MAXP]; 17 long long int cur[MAXP]; 18 long long int pre[MAXP]; 19 long long int stack[MAXE]; 20 long long int dep[MAXP]; 21 long long int ent; 22 long long int n,m,s,t,cot; 23 void add(long long int start,long long int last,long long int f) 24 { 25 edge[ent].s=start; 26 edge[ent].t=last; 27 edge[ent].f=f; 28 edge[ent].next=head[start]; 29 head[start]=ent++; 30 edge[ent].s=last; 31 edge[ent].t=start; 32 edge[ent].f=0; 33 edge[ent].next=head[last]; 34 head[last]=ent++; 35 } 36 bool bfs(long long int S,long long int T) 37 { 38 memset(pre,-1,sizeof(pre)); 39 pre[S]=0; 40 queue<long long int>q; 41 q.push(S); 42 while(!q.empty()) 43 { 44 long long int temp=q.front(); 45 q.pop(); 46 for(long long int i=head[temp]; i!=-1; i=edge[i].next) 47 { 48 long long int temp2=edge[i].t; 49 if(pre[temp2]==-1&&edge[i].f) 50 { 51 pre[temp2]=pre[temp]+1; 52 q.push(temp2); 53 } 54 } 55 } 56 return pre[T]!=-1; 57 } 58 long long int dinic(long long int start,long long int last) 59 { 60 long long int flow=0,now; 61 while(bfs(start,last)) 62 { 63 long long int top=0; 64 memcpy(cur,head,sizeof(head)); 65 long long int u=start; 66 while(1) 67 { 68 if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流 69 { 70 long long int minn=INT_MAX; 71 for(long long int i=0; i<top; i++) 72 { 73 if(minn>edge[stack[i]].f) 74 { 75 minn=edge[stack[i]].f; 76 now=i; 77 } 78 } 79 flow+=minn; 80 for(long long int i=0; i<top; i++) 81 { 82 edge[stack[i]].f-=minn; 83 edge[stack[i]^1].f+=minn; 84 } 85 top=now; 86 u=edge[stack[top]].s; 87 } 88 for(long long int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边 89 if(edge[i].f&&pre[edge[i].t]==pre[u]+1) 90 break; 91 if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯 92 { 93 if(top==0)break; 94 pre[u]=-1; 95 u=edge[stack[--top]].s; 96 } 97 else//如果找到了继续运行 98 { 99 stack[top++]=cur[u]; 100 u=edge[cur[u]].t; 101 } 102 } 103 } 104 return flow; 105 } 106 void dfs(long long int u) 107 { 108 cot++; 109 dep[u]=1; 110 for(long long int i=head[u];i!=-1;i=edge[i].next) 111 { 112 long long int v=edge[i].t; 113 if(!dep[v]&&edge[i].f>0) 114 { 115 dfs(v); 116 } 117 } 118 } 119 int main() 120 { 121 while(~scanf("%lld%lld",&n,&m)) 122 { 123 s=0; 124 t=n+1; 125 ent=0; 126 long long int cost,u,v; 127 long long int ans=0; 128 memset(head,-1,sizeof(head)); 129 for(int i=1; i<=n; i++) 130 { 131 scanf("%lld",&cost); 132 if(cost>0) 133 { 134 add(s,i,cost); 135 ans+=cost; 136 } 137 else add(i,t,-cost); 138 } 139 for(int i=1; i<=m; i++) 140 { 141 scanf("%lld%lld",&u,&v); 142 add(u,v,INT_MAX); 143 } 144 memset(dep,0,sizeof(dep)); 145 long long int flow=dinic(s,t); 146 cot=0; 147 dfs(s); 148 printf("%lld ",cot-1); 149 printf("%lld ",ans-flow); 150 } 151 return 0; 152 } |