最大权闭合子图模板题

题目链接

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,所以由上司向下属连边。

猜你喜欢

转载自blog.csdn.net/strangeDDDF/article/details/86004832
今日推荐