[tyvj 1452] 选做作业 {最小割,最大子权闭合图,网络流}

版权声明:~~~感谢支持! https://blog.csdn.net/qq_39897867/article/details/88314498

题目

http://www.joyoi.cn/problem/tyvj-1452


解题思路

对于一个图,如果上面有环,显然选不了,可以先用拓扑排序找环。

然后考虑最大子权闭合图(我也不太懂),对于正数点用原点连接,而负数点则连接汇点——容量为权值的绝对值

跑一遍dinic即可。


代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define rep(i,x,y) for (register int i=x;i<=y;i++)
using namespace std;
const int N=510,inf=2147483647/3;
struct node{int to,next,w;}a[N*N*2];
int n,cnt,head[N],in[N],v[N],ans,dep[N],s,t,m[N],edge[N][N];
queue<int>q;
void addq(int x,int y){
	a[++cnt]=(node){y,head[x],0},head[x]=cnt,in[y]++;
}
void addw(int x,int y,int w){
	a[++cnt]=(node){y,head[x],w};head[x]=cnt;
	a[++cnt]=(node){x,head[y],0};head[y]=cnt;
}
void tops()
{
	rep(i,1,n) if(!in[i]) q.push(i);
	while(!q.empty()){
		int x=q.front(); q.pop();
		for(register int i=head[x];i;i=a[i].next){
			int y=a[i].to;
			in[y]--;
			if(!in[y]) q.push(y);
		}
	}
}
bool bfs()
{
	memset(dep,0,sizeof(dep));
	while(!q.empty()) q.pop();
	q.push(s);dep[s]=1;
	while(!q.empty()){
		int x=q.front();q.pop();
		for(register int i=head[x];i;i=a[i].next){
			int y=a[i].to;
			if(!dep[y]&&a[i].w){
				dep[y]=dep[x]+1;
				if(y==t) return 1;
				q.push(y);
			}
		}
	}
	return 0;
}
int dinic(int x,int flow)
{
	int rest=0,k;
	if(x==t) return flow;
	for(register int i=head[x];i;i=a[i].next){
		int y=a[i].to;
		if(dep[x]+1==dep[y]&&a[i].w){
			rest+=(k=dinic(y,min(a[i].w,flow-rest)));
			a[i].w-=k;a[i^1].w+=k;
			if(rest==flow) return flow;
		}
	}
	if (!rest) dep[x]=0;
	return rest;
}
int main()
{
	scanf("%d",&n);
	rep(i,1,n){
		scanf("%d%d",&v[i],&m[i]);
		rep(j,1,m[i])
			scanf("%d",&edge[i][j]),addq(edge[i][j],i);
	}
	tops();
	cnt=1;s=n+1;t=n+2;
	memset(head,0,sizeof(head));
	rep(i,1,n){
		if(in[i]) continue;
		if(v[i]<0) addw(i,t,-v[i]);	else addw(s,i,v[i]),ans+=v[i];
		rep(j,1,m[i]){
		  if(in[edge[i][j]]) continue;
		  addw(i,edge[i][j],inf);
		}
	}
	while(bfs()) ans-=dinic(s,inf);
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/88314498