Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define ll long long
using namespace std;
const int inf=1e10;
const int N=10000;
const int M=400000;
struct node{int y,n,v;}e[M];
int lin[M],d[N],v[N],len=1,val,S,T,n,m,x,y,num=0;
ll maxflow=0,tot=0;
void read(int x,int y,int v)
{e[++len].y=y,e[len].v=v,e[len].n=lin[x],lin[x]=len;}
void add(int x,int y,int v)
{read(x,y,v),read(y,x,0);}
bool bfs(int S,int T){
queue<int> q;memset(d,0,sizeof(d));
d[S]=1,q.push(S);
while(q.size()){
int x=q.front();q.pop();
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(!e[i].v||d[y])continue;
d[y]=d[x]+1;q.push(y);
}
}
return d[T]>0;
}
ll dfs(int x,int T,ll minf){
ll flow=0,sum=0;
if(x==T)return minf;
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(e[i].v&&d[y]==d[x]+1){
flow=dfs(y,T,min(minf,1LL*e[i].v));
if(!flow)d[y]=0;
e[i].v-=flow,e[i^1].v+=flow,minf-=flow,sum+=flow;
if(!minf)return sum;
}
}return sum;
}
void dinic(){
while(bfs(S,T))
maxflow+=dfs(S,T,inf);
}
void search(int x){
v[x]=1;
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(v[y]||e[i].v==0)continue;
if(x!=T)num++;v[y]=1;
search(y);
}
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%d%d",&n,&m); S=n+1,T=S+1;
rep(i,1,n){scanf("%d",&val);if(val>=0)tot+=val,add(S,i,val);else add(i,T,-val);}
rep(i,1,m){scanf("%d%d",&x,&y);add(x,y,inf);}
dinic();
search(S);
cout<<num<<" "<<tot-maxflow;
return 0;
}
- 如果上司被开除那么他的下属也会被开除,假设一条流x->y,如果流到x,必定会留到y,所以由上司向下属连边。