• 51nod1325 两棵树的问题


    题意

    先枚举一个点必须选,设该点为(x)

    将两棵树都以(x)为根,对于点(y),如果选(y)必须要选(fa_y),于是就变成了了最大权闭合子图。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=55;
    const int inf=1e9;
    int n,S,T,ans;
    int val[maxn];
    inline int read()
    {
        char c=getchar();int res=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
        return res*f;
    }
    struct Edge
    {
    	int cnt_edge;
    	int head[maxn],to[maxn<<1],nxt[maxn<<1],fa[maxn];
    	inline void add_edge(int u,int v)
    	{
    		nxt[++cnt_edge]=head[u];
    		head[u]=cnt_edge;
    		to[cnt_edge]=v;
    	}
    }E1,E2;
    void dfs(int x,Edge& E)
    {
    	for(int i=E.head[x];i;i=E.nxt[i])
    	{
    		int y=E.to[i];
    		if(y==E.fa[x])continue;
    		E.fa[y]=x;dfs(y,E);
    	}
    }
    struct Dinic
    {
    	int cnt_edge;
    	int head[maxn],nxt[maxn<<3],to[maxn<<3],flow[maxn<<3],cur[maxn],dep[maxn];
    	inline void clear()
    	{
    		memset(head,0,sizeof(head));
    		cnt_edge=1;
    	}
    	inline void add_edge(int u,int v,int w)
    	{
    		nxt[++cnt_edge]=head[u];
    		head[u]=cnt_edge;
    		to[cnt_edge]=v;
    		flow[cnt_edge]=w;
    	}
    	inline void addflow(int u,int v,int w){add_edge(u,v,w),add_edge(v,u,0);}
    	inline bool bfs()
    	{
    		memset(dep,0,sizeof(dep));
    		for(int i=0;i<=n+1;i++)cur[i]=head[i];
    		queue<int>q;
    		q.push(S);dep[S]=1;
    		while(!q.empty())
    		{
    			int x=q.front();q.pop();
    			for(int i=head[x];i;i=nxt[i])
    			{
    				int y=to[i];
    				if(dep[y]||!flow[i])continue;
    				dep[y]=dep[x]+1;q.push(y);
    			}
    		}
    		return dep[T]>0;
    	}
    	int dfs(int x,int goal,int lim)
    	{
    		if(x==goal||!lim)return lim;
    		int res=lim;
    		for(int i=cur[x];i;i=nxt[i])
    		{
    			cur[x]=i;
    			int y=to[i];
    			if(dep[y]!=dep[x]+1||!flow[i])continue;
    			int tmp=dfs(y,goal,min(res,flow[i]));
    			if(!tmp)dep[y]=0;
    			flow[i]-=tmp,flow[i^1]+=tmp,res-=tmp;
    			if(!res)break;
    		}
    		return lim-res;
    	}
    	inline int dinic()
    	{
    		int res=0;
    		while(bfs())res+=dfs(S,T,inf);
    		return res;
    	}
    }e;
    inline void solve(int root)
    {
    	for(int i=1;i<=n;i++)E1.fa[i]=E2.fa[i]=0;
    	dfs(root,E1),dfs(root,E2);
    	e.clear();
    	for(int i=1;i<=n;i++)
    	{
    		if(E1.fa[i])e.addflow(i,E1.fa[i],inf);
    		if(E2.fa[i]&&E2.fa[i]!=E1.fa[i])e.addflow(i,E2.fa[i],inf);
    	}
    	int res=0;
    	for(int i=1;i<=n;i++)
    		if(val[i]>=0)res+=val[i],e.addflow(S,i,val[i]);
    		else e.addflow(i,T,-val[i]);
    	ans=max(ans,res-e.dinic());
    }
    int main()
    {
    	n=read();
    	S=0,T=n+1;
    	for(int i=1;i<=n;i++)val[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int u=read()+1,v=read()+1;
    		E1.add_edge(u,v),E1.add_edge(v,u);
    	}
    	for(int i=1;i<n;i++)
    	{
    		int u=read()+1,v=read()+1;
    		E2.add_edge(u,v),E2.add_edge(v,u);
    	}	
    	for(int i=1;i<=n;i++)solve(i);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    [笔记]JavaScript获得对象属性个数的方法
    [转]去除inline-block元素间间距的N种方法
    表单提交成功如何弹出提示
    [笔记]CSS样式声明顺序
    [转]浏览器渲染机制——一定要放在body底部的js引用
    [笔记]使用clearfix清除浮动
    [转]jQuery.validate插件在失去焦点时执行验证代码
    验证常用正则表达式
    字符串与Objec之间互相转换
    $.extend()
  • 原文地址:https://www.cnblogs.com/nofind/p/13051610.html
Copyright © 2020-2023  润新知