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;
}
51nod 1325 两棵树的问题(最大权闭合子图)的更多相关文章
- 51 NOD 1325 两棵树的问题
Discription 对于 100% 的数据, N<=50. solution: 发现N比较小,所以我们可以花O(N^2)的代价枚举两颗树的联通块的LCA分别是哪个点,然后现在问题就变成了:选 ...
- LeetCode——Same Tree(判断两棵树是否相同)
问题: Given two binary trees, write a function to check if they are equal or not. Two binary trees are ...
- WPF的两棵树与绑定
原文:WPF的两棵树与绑定 先建立测试基类 public class VisualPanel : FrameworkElement { protected VisualCollection Chi ...
- element ui改写实现两棵树
使用element ui组件库实现一个table的两棵树的效果 效果如下,左边树自动展开一级,右边树默认显示楼层,然后可以一个个展开 代码如下 <el-table :data="rel ...
- [51nod1325]两棵树的问题
description 题面 solution 点分治+最小割. 点分必选的重心,再在树上dfs判交,转化为最大权闭合子图. 可以做\(k\)棵树的情况. code #include<iostr ...
- HDU 6315.Naive Operations-线段树(两棵树合并)(区间单点更新、区间最值、区间求和)+思维 (2018 Multi-University Training Contest 2 1007)
6315.Naive Operations 题意很好理解,但是因为区间求和求的是向下取整的a[i]/b[i],所以直接分数更新区间是不对的,所以反过来直接当a[i]==b[i]的时候,线段树对应的位置 ...
- 判断两棵树是否相等 leecode
很简单 提交代码 https://oj.leetcode.com/problems/same-tree/ iven two binary trees, write a function to chec ...
- 51nod 1551 集合交易 最大权闭合子图
题意: 市场中有n个集合在卖.我们想买到满足以下要求的一些集合,所买到集合的个数要等于所有买到的集合合并后的元素的个数. 每个集合有相应的价格,要使买到的集合花费最小. 这里我们的集合有一个特点:对于 ...
- hdu-3015 Disharmony Trees---离散化+两个树状数组
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3015 题目大意: 有一些树,这些树的高度和位置给出.现在高度和位置都按从小到大排序,对应一个新的ra ...
随机推荐
- Chrome添加Unity本地文档引擎
前提:输入Unity后出来的第一连接 浏览器的设置: 分别填入: UnityDocs unity3d.com/cn file:///Applications/Unity/Documentation/e ...
- 第九章 Python之面向对象
面向对象编程 面向对象编程是一种程序设计思想,它把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数 面向过程的程序设计把计算机程序视为一系列命令的集合,即一组函数的顺序执行.为了简化程序设计 ...
- mac上virtualbox创建vm需要注意启动顺序
创建好vm后,需要注意,按照下图,将vm的启动顺序设置成 硬盘,不然,你会一直处于安装的逻辑中
- KVM虚拟机相关步骤
KVM是Kernel-based Virtual Machine的简称,是一个开源的虚拟化模块,该文档是基于CentOS 7.4环境操作的 一.操作系统安装 本文采用的是CentOS 7.4 1.查看 ...
- javascript深度克隆函数deepClone
javascript深度克隆函数deepClone function deepClone(obj) { var _toString = Object.prototype.toString; // nu ...
- WinServer-PowerShell基础
命令的参数: [-name] 这个参数必须要有,string表示name参数接受什么样的实参,<>表示参数可以接受的实参类型,通常出现set get add都会伴随着必须参数 [-name ...
- 洛谷—— P1640 [SCOI2010]连续攻击游戏
https://www.luogu.org/problem/show?pid=1640 题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1, ...
- MyEclipse打包可运行的jar包
详细步骤: Export... -> java -> Runnable JAR file Launch configuration:选择main方法所在的文件/类 Export desti ...
- SICP 习题 (1.41)解题总结
SICP 习题1.41 看似和周边的题目没有关系,突然叫我们去定义一个叫double的过程,事实上这道题的核心还是高阶函数. 题目要求我们定义一个过程double,它以一个过程作为參数,这个作为參数的 ...
- 5.Git使用详细教程
转自:https://www.cnblogs.com/seven-ahz/p/7712125.html 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的 ...