description

题面

solution

点分治+最小割。

点分必选的重心,再在树上dfs判交,转化为最大权闭合子图。

可以做\(k\)棵树的情况。

code

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define RG register
#define il inline
using namespace std;
typedef long long ll;
typedef double dd;
const int N=205;
const int M=20;
const int mod=1e9+7;
const int inf=2147483647;
il ll read(){
RG ll d=0,w=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')d=d*10+ch-48,ch=getchar();
return d*w;
} int n,sum,rt,ans=-inf,val[N],ret;
int head[N],nxt[N<<1],to[N<<1],cnt;
il void add(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
} int S,T,dhead[N],dnxt[N<<1],dto[N<<1],dval[N<<1],dcnt;
il void addedge(int u,int v,int w){
dto[++dcnt]=v;
dnxt[dcnt]=dhead[u];
dval[dcnt]=w;
dhead[u]=dcnt; dto[++dcnt]=u;
dnxt[dcnt]=dhead[v];
dval[dcnt]=0;
dhead[v]=dcnt;
} queue<int>Q;int dep[N],cur[N];
il bool bfs(){
for(RG int i=1;i<=T;i++)dep[i]=0;
while(!Q.empty())Q.pop();
dep[S]=1;Q.push(S);
while(!Q.empty()){
RG int u=Q.front();Q.pop();
for(RG int i=dhead[u];i;i=dnxt[i]){
RG int v=dto[i];
if(!dep[v]&&dval[i]){
dep[v]=dep[u]+1;
Q.push(v);
}
}
}
return dep[T];
} int dfs(int u,int t,int power){
if(u==t)return power;
for(RG int &i=cur[u];i;i=dnxt[i]){
RG int v=dto[i];
if(dep[v]==dep[u]+1&&dval[i]){
RG int d=0;
if(d=dfs(v,t,min(power,dval[i]))){
dval[i]-=d;
dval[i^1]+=d;
return d;
}
}
}
return 0;
} il int Dinic(){
RG int ret=0,d;
while(bfs()){
for(RG int i=1;i<=T;i++)cur[i]=dhead[i];
while(d=dfs(S,T,inf))ret+=d;
}
return ret;
} int sz[N],w[N],cover[N],tot,pd[N];bool vis[N];
void dfscover(int u,int fa){
cover[u]=tot;pd[u]=dhead[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa||vis[v])continue;
dfscover(v,u);
}
}
void dfspd(int u,int fa){
RG int x=u>n?u-n:u;pd[x]++;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa)continue;
RG int y=v>n?v-n:v;
if(cover[y]==tot)dfspd(v,u);
}
} void dfsadd(int u,int fa){
RG int x=u>n?u-n:u;if(u<=n&&val[u]>0)ret+=val[u];
if(u<=n&&val[x])
val[x]>0?addedge(S,x,val[x]):addedge(x,T,-val[x]);
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa)continue;
RG int y=v>n?v-n:v;
if(cover[y]==tot&&pd[y]==2){
addedge(y,x,inf);
dfsadd(v,u);
}
}
}
il void calc(int u){
tot++;dcnt=1;ret=0;
S=sum+1;T=sum+2;dhead[S]=dhead[T]=0;
dfscover(u,0);
dfspd(u,0);dfspd(u+n,0);
//addedge(S,u,inf);??????
dfsadd(u,0);dfsadd(u+n,0);
ans=max(ans,ret-Dinic());
} void getrt(int u,int fa){
sz[u]=1;w[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa||vis[v])continue;
getrt(v,u);sz[u]+=sz[v];
w[u]=max(w[u],sz[v]);
}
w[u]=max(w[u],sum-sz[u]);
if(w[rt]>w[u])rt=u;
}
void solve(int u){
calc(u);vis[u]=1;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(vis[v])continue;
sum=sz[v];rt=0;
getrt(v,0);
solve(rt);
}
} int main()
{
n=read();
for(RG int i=1;i<=n;i++)val[i]=read();
for(RG int i=1,u,v;i<n;i++){
u=read()+1;v=read()+1;add(u,v);add(v,u);
}
for(RG int i=1,u,v;i<n;i++){
u=read()+1;v=read()+1;add(u+n,v+n);add(v+n,u+n);
}
w[0]=sum=n;rt=0;
getrt(1,0);
solve(rt);
printf("%d\n",ans);
return 0;
}

Question

写最小割的时候,如果使用

addedge(S,u,inf);

来强制重心必选

就会\(WA\)在最后一个数据点

如果不写这句话就\(A\)掉了

如果有\(dalao\)知道是为什么的话欢迎在下方的评论给出建议

[51nod1325]两棵树的问题的更多相关文章

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

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

  2. WPF的两棵树与绑定

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

  3. element ui改写实现两棵树

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

  4. 51 NOD 1325 两棵树的问题

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

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

    首先如果点权全都为正,就可以直接选所有的点. 活在梦里.. 考虑枚举一个点\(i\),作为我们选择的集合中的一个点. 然后我们把另一个点\(j\)选入集合的时候必须把两棵树中\(i\)和\(j\)路径 ...

  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. hdu-3015 Disharmony Trees---离散化+两个树状数组

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

  9. LeetCode——1305. 两棵二叉搜索树中的所有元素

    给你 root1 和 root2 这两棵二叉搜索树. 请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序.. 示例 1: 输入:root1 = [2,1,4], root2 = [1,0 ...

随机推荐

  1. iOS 中的正则表达式符号

    最近重新看了一遍 iOS 的正则文档,简单翻译下文档中涉及到的符号 1.正则表达式元字符 符号 说明 \a 响铃, \u0007 \A 匹配输入的开始,只匹配第一行,也就是忽略多行选项 \b 不在[] ...

  2. 腾讯WeTest开启“测试扶持计划”赠送重磅福利(含MTSC/TiD门票)

    WeTest导语 伴随着互联网行业的发展,与各行各业的连接更加紧密,竞争也变得越发激烈,用户对于产品的体验开始变得更加“挑剔”.然而目前互联网产品却始终受到各类质量问题的困扰.以兼容问题为例,应用平台 ...

  3. 「日常训练」Regular Bridge(Codeforces Round 306 Div.2 D)

    题意与分析 图论基础+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #defi ...

  4. Qt 解析EXcel文件

    写代码需要将excel中的文件导入到数据库中 网上找到以为大神写的,但是当初没有保存,也没有找到 我几乎是原分不动拔下来的,希望大神莫怪 void AddDialog::readExcel(QStri ...

  5. 现实世界中的 Python

    Python 有多稳定? 非常稳定. 自 1991 年起大约每隔 6 到 18 个月就会推出新的稳定发布版,这种状态看来还将持续下去. 目前主要发布版本的间隔通常为 18 个月左右. 开发者也会推出旧 ...

  6. Python教程:Python中的for 语句

    Python 中的 for 语句与你在 C 或 Pascal 中可能用到的有所不同. Python教程 中的 for 语句并不总是对算术递增的数值进行迭代(如同 Pascal),或是给予用户定义迭代步 ...

  7. 如何处理 jQuery $(window).resize() 中的方法被多次执行的小问题

    引言: 估计很多同志们在编写浏览器resize()的方法时,都会遇到这样的情况: 当拖动浏览器的边角时,页面中的一些效果随浏览器大小的改变而触发,这一过程开始到结束,resize() 中的方法被执行了 ...

  8. appium关键字:

    ## Appium 服务关键字 <expand_table> |关键字|描述|实例||----|-----------|-------||`automationName`|你想使用的自动化 ...

  9. 解决CentOS: Failed to start The Apache HTTP Server.

    使用systemctl status httpd.service命令查看服务状态,发现有报错 然后将此配置文件/etc/httpd/conf.d/wordpress.conf的内容全部清空,修改为: ...

  10. 【第五章】MySQL数据库的安全机制

    MySQL权限表MySQL用户管理MySQL权限管理SSL加密连接