首先如果点权全都为正,就可以直接选所有的点。

活在梦里。。

考虑枚举一个点\(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;
}

51nod 1325 两棵树的问题(最大权闭合子图)的更多相关文章

  1. 51 NOD 1325 两棵树的问题

    Discription 对于 100% 的数据, N<=50. solution: 发现N比较小,所以我们可以花O(N^2)的代价枚举两颗树的联通块的LCA分别是哪个点,然后现在问题就变成了:选 ...

  2. LeetCode——Same Tree(判断两棵树是否相同)

    问题: Given two binary trees, write a function to check if they are equal or not. Two binary trees are ...

  3. WPF的两棵树与绑定

    原文:WPF的两棵树与绑定   先建立测试基类 public class VisualPanel : FrameworkElement { protected VisualCollection Chi ...

  4. element ui改写实现两棵树

    使用element ui组件库实现一个table的两棵树的效果 效果如下,左边树自动展开一级,右边树默认显示楼层,然后可以一个个展开 代码如下 <el-table :data="rel ...

  5. [51nod1325]两棵树的问题

    description 题面 solution 点分治+最小割. 点分必选的重心,再在树上dfs判交,转化为最大权闭合子图. 可以做\(k\)棵树的情况. code #include<iostr ...

  6. HDU 6315.Naive Operations-线段树(两棵树合并)(区间单点更新、区间最值、区间求和)+思维 (2018 Multi-University Training Contest 2 1007)

    6315.Naive Operations 题意很好理解,但是因为区间求和求的是向下取整的a[i]/b[i],所以直接分数更新区间是不对的,所以反过来直接当a[i]==b[i]的时候,线段树对应的位置 ...

  7. 判断两棵树是否相等 leecode

    很简单 提交代码 https://oj.leetcode.com/problems/same-tree/ iven two binary trees, write a function to chec ...

  8. 51nod 1551 集合交易 最大权闭合子图

    题意: 市场中有n个集合在卖.我们想买到满足以下要求的一些集合,所买到集合的个数要等于所有买到的集合合并后的元素的个数. 每个集合有相应的价格,要使买到的集合花费最小. 这里我们的集合有一个特点:对于 ...

  9. hdu-3015 Disharmony Trees---离散化+两个树状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3015 题目大意: 有一些树,这些树的高度和位置给出.现在高度和位置都按从小到大排序,对应一个新的ra ...

随机推荐

  1. ZBrush中如何对模型进行减面操作

    Decimation Master是ZBrush 4R8自带的一个插件.中文名叫减面大师.其功能非常强大,也非常的方便,可以帮助我们提高效率,减少电脑资源损耗.作为一名3D美术师是必须掌握的一个技术. ...

  2. 路飞学城Python-Day40(第四模块复习题)

    数据库 一.简答题 1.说说你所知道的MySQL数据库存储引擎,InnoDB存储引擎和MyISM存储引擎的区别? 1.InnoDB存储引擎(MySQL默认存储引擎),支持事务,其设计目标主要面向联机事 ...

  3. 队列Queue的get方法

    写了一段生产者消费者模型的代码: from time import sleep from random import randint, random from multiprocessing impo ...

  4. How Google Backs Up The Internet Along With Exabytes Of Other Data

    出处:http://highscalability.com/blog/2014/2/3/how-google-backs-up-the-internet-along-with-exabytes-of- ...

  5. CSS布局总结(二)

    前言:今天实训课依旧很水,继续总结,今天主要补了一下布局的知识.响应式的作业还没做完... 一.两列布局 html部分 <div class="parent"> < ...

  6. 如何在React-Native上使用Typescript

    首先安装脚手架: $ yarn global add create-react-native-app 创建项目: create-react-native-app xxx 进入项目并启动: cd xxx ...

  7. C文件I/O超详细教程

    本文主要参考了C Primer Plus (5th & 6th Edition) 您可以选择本文的部分内容来读,有些内容对于不熟悉MS-DOS的读者可能过于晦涩难懂. C语言文件基本知识 文件 ...

  8. vue如何根据返回的值对元素进行样式渲染

    1.最终显示样式: 需要:根据任务状态值,显示不同颜色的原点表示任务状态,以及对优先级的数据,进行☆标记 2.代码实现: 在<el-table-column>中需要显示的内容前面,添加图标 ...

  9. 如何让myeclipse左边选中文件后自动关联右边树

    在左侧项目树的右上角下拉菜单里有link with editor 点击即可

  10. xmllint命令

    xmllint是一个很方便的处理及验证xml的工具,linux下只要安装libxml2就可以使用这个命令,下面整理一些常用功能 1. --format 此参数用于格式化xml,使其具有良好的可读性. ...