题目大意:

给定一颗黑白树.允许删除一个白点.最大化删点后无法与删点前距自己最远的黑点连通的黑点个数.并求出方案数.

题解:

这道题很棒棒啊.

一开始想了一个做法,要用LCT去搞,特别麻烦而且还是\(O(nlogn)\)的

% 了vfk的题解才知道这道题居然是\(O(n)\)的...


我们有一个结论:一个点到其最远点的路径一定经过树的直径的重心.

因为所有直径的重心一定相同,所以我们知道重心最多有两个,并且一定连续.

所以我们将重心提至根,以新的根重新建树.那么我们现在就可以发现我们要切断的所有路径一定都经过根.

所以我们考虑枚举删除的白点.其子树当中的所有黑点所连出的路径一定都被切断

那么我们现在考虑计算除这些子树外的路径.

对于同处于根的同一个儿子中的其他的黑点一定无法被切断.

这时我们要讨论一下我们当前的枚举点是否处于到根路径前2大的黑点所在的路径.

如果是,那么我们仍需要讨论一下这个路径是否全由这个以这个点为根的子树更新来.

然后再瞎XX判一些东西即可.(不具体说是什么是因为说不清楚...还不懂的话自己YY吧)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
struct Edge{
int to,next,dis;
}G[maxn<<1];
int head[maxn],cnt,rt;
void add(int u,int v,int d){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
G[cnt].dis = d;
}
bool col[maxn];
int f[maxn],g[maxn],pos;
#define v G[i].to
void dfs(int u,int f,int *dis){
if(col[u] && dis[pos] < dis[u]) pos = u;
for(int i = head[u];i;i=G[i].next){
if(v == f) continue;
dis[v] = dis[u] + G[i].dis;
dfs(v,u,dis);
}
}
int belong[maxn],siz[maxn];
void dfs2(int u,int fa,int d){
if(fa == rt) belong[u] = u;
else belong[u] = belong[fa];
siz[u] = col[u];
for(int i = head[u];i;i=G[i].next){
if(v == fa) continue;
dfs2(v,u,d+G[i].dis);
siz[u] += siz[v];
}
if(siz[u]){
f[u] = d;g[u] = 1;
for(int i = head[u];i;i=G[i].next){
if(v == fa) continue;
if(f[v] > f[u]){
f[u] = f[v];
g[u] = g[v];
}else if(f[v] == f[u]) g[u] += g[v];
}
}
}
#undef v
int main(){
int n,m;read(n);read(m);
for(int i=1,x;i<=m;++i){
read(x);col[x] = true;
}
for(int i=1,u,v,d;i<n;++i){
read(u);read(v);read(d);
add(u,v,d);add(v,u,d);
}
pos = 0;dfs(1,1,f);
int x = pos;pos = 0;
dfs(x,x,g); memset(f,0,sizeof f);
dfs(pos,pos,f);
rt = 0;
for(int i=1;i<=n;++i){
if(f[i] + g[i] == f[x]){
if(rt == 0) rt = i;
else if(abs(f[i] - g[i]) < abs(f[rt] - g[rt])) rt = i;
}
}
memset(f,0,sizeof f);
memset(g,0,sizeof g);
dfs2(rt,rt,0);
int mx = 0,cmx = 0,mxid = 0,cmxid = 0;
for(int i = head[rt];i;i=G[i].next){
int v = G[i].to;
if(siz[v] == 0) continue;
if(f[v] > mx){
cmx = mx;cmxid = mxid;
mx = f[v];mxid = v;
}else if(f[v] == mx){
if(mx == cmx){
mxid = cmxid = 0;
break;
}else{
cmx = mx;cmxid = mxid;
mx = f[v];mxid = v;
}
}else if(f[v] > cmx){
cmx = f[v];
cmxid = v;
}
}
int ans = 0,ans_cnt = 0;
if(col[rt] == false) ans = m,ans_cnt = 1;
for(int i = 1;i<=n;++i){
if(i == rt || col[i]) continue;
int res = siz[i];
if(siz[i]&&(f[i] == f[belong[i]])&&(g[i] == g[belong[i]])){
if(belong[i] == mxid){
if(f[mxid] > f[cmxid]) res += m - siz[mxid];
else res += siz[cmxid];
}else if(belong[i] == cmxid) res += siz[mxid];
}
if(res > ans) ans = res,ans_cnt = 1;
else if(res == ans) ++ ans_cnt;
}
printf("%d %d\n",ans,ans_cnt);
return 0;
}

uoj problem 11 ydc的大树的更多相关文章

  1. uoj problem 10

    uoj problem 10 题目大意: 给定任务若干,每个任务在\(t_i\)收到,需要\(s_i\)秒去完成,优先级为\(p_i\) 你采用如下策略: 每一秒开始时,先收到所有在该秒出现的任务,然 ...

  2. Problem 11

    Problem 11 # Problem_11.py """ In the 20×20 grid below, four numbers along a diagonal ...

  3. 【UTR #1】ydc的大树

    [UTR #1]ydc的大树 全网唯一一篇题解我看不懂 所以说一下我的O(nlogn)做法: 以1号点为根节点 一个黑点如果有多个相邻的节点出去都能找到最远的黑点,那么这个黑点就是无敌的 所以考虑每个 ...

  4. UOJ #11. 【UTR #1】ydc的大树

    题目描述: ydc有一棵n个结点的黑白相间的大树,从1到n编号. 这棵黑白树中有m个黑点,其它都是白点. 对于一个黑点我们定义他的好朋友为离他最远的黑点.如果有多个黑点离它最远那么都是它的好朋友.两点 ...

  5. UOJ #11 - 【UTR #1】ydc的大树(换根 dp)

    题面传送门 Emmm--这题似乎做法挺多的,那就提供一个想起来写起来都不太困难的做法吧. 首先不难想到一个时间复杂度 \(\mathcal O(n^2)\) 的做法:对于每个黑点我们以它为根求出离它距 ...

  6. leetcode problem 11 Container With Most Water

    Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...

  7. uoj problem 31 猪猪侠再战括号序列

    题目大意: 给定一个长度为2n的括号序列.定义一个关于区间[l,r]的翻转操作为位置平移对调. 即翻转")))()("可以得到"()()))((" 用不超过n次 ...

  8. uoj problem 14 DZY Loves Graph

    题目: DZY开始有 \(n\) 个点,现在他对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 \(1\) 开始编号)有可能的三种情况: Add a b: 表示在 \( ...

  9. uoj problem 21 缩进优化

    题目: 小O是一个热爱短代码的选手.在缩代码方面,他是一位身经百战的老手.世界各地的OJ上,很多题的最短解答排行榜都有他的身影.这令他感到十分愉悦. 最近,他突然发现,很多时候自己的程序明明看起来比别 ...

随机推荐

  1. 安卓编译出错: Process 'command 'C:\Java\jdk1.8.0_51\bin\java.exe'' finished with non-zero exit value 1 解决!

    安卓编译出错: Process 'command 'C:\Java\jdk1.8.0_51\bin\java.exe'' finished with non-zero exit value 1 解决! ...

  2. Earth Hour(最短路)

    Earth Hour Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total ...

  3. TFS 中工作项的定制-修改工作流

    我们都会用到TFS中的工作项.一般来说,最主要的会用到任务.bug这些工作流来进行项目管理里.但我们发现,实际上,有些模板中的工作流并不能完全符合我们的需要,因此我们会进行工作流的定制操作.下面就会通 ...

  4. What is the difference between iterations and epochs in Convolution neural networks?

    https://stats.stackexchange.com/questions/164876/tradeoff-batch-size-vs-number-of-iterations-to-trai ...

  5. 次小生成树Tree

    次小生成树Treehttps://www.luogu.org/problemnew/show/P4180 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正 ...

  6. MySQL一些常见查询方式

    1.查询端口号命令: show global variables like 'port'; 2.查看版本号: select version(); 3.查看默认安装的MySQL的字符集 show var ...

  7. lazyload.js参数说明

    lazyload.js是jQuery的一个插件,可以用来实现图片异步加载. lazyload插件如何添加参数: $("img").lazyload({ //参数添加到此位置,建议一 ...

  8. 深度问答之提取语料,导入了yml模块

    根据目录下的yml文件循环创建同名文件夹,并从yml文件读取问答并给每个文件夹写入question和answer文件 #!/usr/bin/env python # coding:utf8 # aut ...

  9. Data Structure Array: Program for array rotation

    http://www.geeksforgeeks.org/array-rotation/ O(n), O(1) #include <iostream> #include <vecto ...

  10. Ubuntu15.10下***搭建及GUI客户端安装

    1.依赖包安装 sudo apt-get install python-pip python-dev build-essential sudo pip install pip sudo apt-get ...