/* 题意简述:一个公司要裁人,给出裁每个人都有个盈利或者损失, 如果一个人的上司被裁那么他也将被裁,现在问怎样裁才能使得公司的收益最大,最大为多少? 分析:因为这里上司和下属之间存在一个依赖关系,下属存在的前提或者是必要条件是其上司的存在, 所以这满足最大闭权闭合图的性质,用最大权闭合图求解即可 这里注意:结果有可能会超过int,需用__int64或者long long */ #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N=5002; const int M=62002; const int INF=1<<30; int t,n,m,tot; int gap[M],dis[M],pre[M],head[N],cur[N],vis[N]; int NE,NV,sink,source; struct Node { int c,pos,next; } E[M*4]; #define FF(i,NV) for(int i=0;i<NV;i++) __int64 sap(int s,int t) { memset(dis,0,sizeof(int)*(NV+1)); memset(gap,0,sizeof(int)*(NV+1)); FF(i,NV) cur[i] = head[i]; int u = pre[s] = s,aug =INF; __int64 maxflow = 0; gap[0] = NV; while(dis[s] < NV) { loop: for(int &i = cur[u]; i != -1; i = E[i].next) { int v = E[i].pos; if(E[i].c && dis[u] == dis[v] + 1) { aug=min(aug,E[i].c); pre[v] = u; u = v; if(v == t) { maxflow += aug; for(u = pre[u]; v != s; v = u,u = pre[u]) { E[cur[u]].c -= aug; E[cur[u]^1].c += aug; } aug =INF; } goto loop; } } if( (--gap[dis[u]]) == 0) break; int mindis = NV; for(int i = head[u]; i != -1 ; i = E[i].next) { int v = E[i].pos; if(E[i].c && mindis > dis[v]) { cur[u] = i; mindis = dis[v]; } } gap[ dis[u] = mindis+1 ] ++; u = pre[u]; } return maxflow; } void addEdge(int u,int v,int c ) { E[NE].c = c; E[NE].pos = v; E[NE].next = head[u]; head[u] = NE++; E[NE].c = 0; E[NE].pos = u; E[NE].next = head[v]; head[v] = NE++; } void dfs(int u) { vis[u]=1; for(int i=head[u]; i!=-1; i=E[i].next) { int v=E[i].pos; if(!vis[v]&&E[i].c>0) { // vis[v]=1;//表示该点未满流 dfs(v); } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { int i,j,add,u,v; __int64 sum=0; source=0,sink=n+1,NE=0,NV=sink+1; memset(head,-1,sizeof(int)*(NV)); memset(vis,0,sizeof(int)*(NV)); for(i=1; i<=n; i++) { scanf("%d",&add); if(add<0) addEdge(i,sink,-add); else { sum+=add; addEdge(source,i,add); } } for(i=1; i<=m; i++) { scanf("%d%d",&u,&v); addEdge(u,v,INF); } __int64 ans=sap(source,sink); int size=0; dfs(0); for(i=1; i<=n; i++) { if(vis[i]) size++; } printf("%d %I64d\n",size,sum-ans); } return 0; } /* 5 5 8 -9 -20 12 -10 1 2 2 5 1 4 3 4 4 5 */