• 51nod 1325 两棵树的问题(最大权闭合子图)


    首先如果点权全都为正,就可以直接选所有的点。
    活在梦里。。
    考虑枚举一个点(i),作为我们选择的集合中的一个点。
    然后我们把另一个点(j)选入集合的时候必须把两棵树中(i)(j)路径上的点全都选入集合。
    似乎想到了什么。
    闭合子图。
    不就是一个最大权闭合子图吗。
    然后我们按最大权闭合子图的模型建图。
    所有正权的点跟(S)连容量为权值的边。
    所有负权的点跟(T)连容量为权值绝对值的边。
    我们把枚举的i作为两个树上的根。
    然后每一个点跟两颗树上的(father)连容量为(INF)的边。
    然后正权总和-最小割就是答案。

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int INF=1e9;
    const int N=110;
    int cnt,head[N];
    struct edge{
    	int to,nxt,flow;
    }e[N*6];
    void add_edge(int u,int v,int flow){
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    	e[cnt].flow=flow;
    }
    int cn,hed[N];
    struct ed{
    	int to,nxt;
    }ee[N*2];
    void add(int u,int v){
    	cn++;
    	ee[cn].nxt=hed[u];
    	ee[cn].to=v;
    	hed[u]=cn;
    }
    int f1[N];
    void dfs1(int u,int f){
    	f1[u]=f;
    	for(int i=hed[u];i;i=ee[i].nxt){
    		int v=ee[i].to;
    		if(v==f)continue;
    		dfs1(v,u);
    	}
    }
    int f2[N];
    void dfs2(int u,int f){
    	f2[u]=f;
    	for(int i=hed[u];i;i=ee[i].nxt){
    		int v=ee[i].to;
    		if(v==f)continue;
    		dfs2(v,u);
    	}
    }
    int dis[N],S,T;
    bool bfs(){
    	memset(dis,-1,sizeof(dis));
    	dis[S]=0;
    	queue<int> q;
    	q.push(S);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=e[i].nxt){
    			int v=e[i].to;
    			if(dis[v]==-1&&e[i].flow){
    				dis[v]=dis[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	if(dis[T]==-1)return false;
    	return true;
    }
    int dfs(int u,int f){
    	if(u==T||f==0)return f;
    	int used=0;
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(dis[v]==dis[u]+1&&e[i].flow){
    			int w=dfs(v,min(f-used,e[i].flow));
    			if(w){
    				e[i].flow-=w;
    				e[i^1].flow+=w;
    				used+=w;
    				if(used==f)return f;
    			}
    		}
    	}
    	if(used==0)dis[u]=-1;
    	return used;
    }
    int tmp;
    void Dinic(){
    	while(bfs())tmp+=dfs(S,INF);
    }
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return sum*f;;
    }
    int n,a[N],tot,ans;
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	for(int i=1;i<n;i++){
    		int u=read()+1,v=read()+1;
    		add(u,v);add(v,u);
    	}
    	for(int i=1;i<n;i++){
    		int u=read()+n+1,v=read()+n+1;
    		add(u,v);add(v,u);
    	}
    	for(int i=1;i<=n;i++){
    		dfs1(i,0);dfs2(i+n,0);
    		cnt=1;memset(head,0,sizeof(head));tot=0;
    		S=0,T=n+1;
    		for(int j=1;j<=n;j++)
    			if(a[j]<0)add_edge(j,T,-a[j]),add_edge(T,j,0);
    			else add_edge(S,j,a[j]),add_edge(j,S,0),tot+=a[j];
    		for(int j=1;j<=n;j++){
    			if(j==i)continue;
    			add_edge(j,f1[j],INF);add_edge(f1[j],j,0);
    			add_edge(j,f2[j+n]-n,INF);add_edge(f2[j+n]-n,j,0);
    		}
    		tmp=0;
    		Dinic();
    		ans=max(ans,tot-tmp);
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Java核心篇,二十三种设计模式(二),结构型——适配器模式
    Java第三十七天,Mybatis框架系列,基于注解的缓存控制
    Java第三十七天,Mybatis框架系列,缓存
    Java第三十七天,Mybatis框架系列,延迟加载(基于 Collection 的实现方式)
    Java第四十五天,SpringBoot框架系列,SpringBoot基础(五)
    第十一篇 Django 【基础篇】
    第十篇 web应用&http协议
    第八篇 (2)jQuery
    第九篇 BootStrap
    第八篇 JavaScript
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10435960.html
Copyright © 2020-2023  润新知