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 ...
随机推荐
- ZBrush中如何做不同图案的遮罩
ZBrush®软件中不仅可以创建矩形遮罩还可以创建有图案的遮罩,且是非常简单有效的,那么究竟怎样做出神奇的效果,本文将为您详细讲解. 有关反转遮罩.清除遮罩的详细内容,请点击:ZBrush中如何反选遮 ...
- IPv6地址分配
- Java学习进阶—高级编程
当你已经熟练的掌握了面向对象中的各种概念后,是否会对这些知识是如何使用的产生浓厚的兴趣?本课程主要针对于已经掌握了JAVA核心开发技术的读者准备,讲解了JAVA多线程.常用类库.IO编程.网络编程.类 ...
- Bzoj 2502: 清理雪道 有上下界网络流_最小流
好长时间没有写网络流了,感觉好手生.对于本题,设一个源点 $s$ 和 $t$.1.由 $s$ 向每个点连一条没有下界,容量为无限大的边,表示以该点为起点.2.由每个点向 $t$ 连一条没有下界,容量为 ...
- 初见UDP_Client
from socket import *ip_prot = ('192.168.55.1',8080)buffer_size = 1024udp_client = socket(AF_INET,SOC ...
- Pyhton学习——Day30
# 内核态# 用户态# 操作系统的运行是在BOIS启动盘读取代码,从硬盘读取到内存中,被操作系统的内核中,一直存在在内存中# 计算机系统的三层结构:应用软件-->操作系统-->硬件# 一般 ...
- 使用iframe标签时如何通过jquery隐藏滚动条
通过mouseover和mouseout事件来控制iframe的滚动条 代码如下:
- Codecademy网站安利 及 javaScript学习
今天发现一个Code教学网站,号称可以利用零碎时间来学习些代码. codecademy (https://www.codecademy.com)
- thinkphp 多个字段的不同关系的查询条件实现 .
tp的$map不同条件默认是 and ,如果要用or<><><><>如下 例如查询Stu表中年龄大于18,或者身高低于180cm的男性(1为男性),(例 ...
- Jquery-操作select下拉菜单
jQuery获取Select选择的Text和Value: 1. var checkText=jQuery("#select_id").find("option:selec ...