题目大意:

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

题解:

这道题很棒棒啊.

一开始想了一个做法,要用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. 浅谈<持续集成、持续交付、持续部署>(一)

    谈谈持续集成,持续交付,持续部署之间的区别 经常会听到持续集成,持续交付,持续部署,三者究竟是什么,有何联系和区别呢?   假如把开发工作流程分为以下几个阶段: 编码 -> 构建 -> 集 ...

  2. Watering Grass(贪心)

    Watering Grass n sprinklers are installed in a horizontal strip of grass l meters long and w meters ...

  3. EasyNVR无插件直播服务器播放页面的集成----单独的播放器样式

    背景需求: EasyNVR自身拥有独立的客户端体系,安卓和IOS拥有各自独立的APP, 安卓下载地址:https://fir.im/EasyNVR: IOS下载可直接在APPstore搜索EasyNV ...

  4. 九度OJ 1347:孤岛连通工程 (最小生成树)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1522 解决:314 题目描述: 现在有孤岛n个,孤岛从1开始标序一直到n,有道路m条(道路是双向的,如果有多条道路连通岛屿i,j则选择最短 ...

  5. ls --color=xxx

      默认的ls是由"ls --color=auto"组成的,假如某个目录中的文件特别多,我不希望显示颜色(可以加快显示),那就需要指定单独的参数. [root@localhost ...

  6. jquery点击一组按钮中的一个,跳转至对应页面处理策略。(如点击订单列表中的一个订单,跳转至该订单的详情)

    将改组按钮的数据设置一个相同的属性(如class),然后每个按钮设置不同的id 当用户点击属性为class的按钮,根据id属性来判断点击的是哪个按钮,然后进行相关操作. 代码示例: <scrip ...

  7. python cookbook第三版学习笔记十六:抽象基类

    假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...

  8. Swift学习笔记十一:方法

         方法是与某些特定类型相关联的功能/函数.在Swift中,结构体和枚举能够定义方法:其实这是Swift与C/Objective-C的主要差别之中的一个. 在Objective-C中,类是唯一能 ...

  9. eclipse安装Activiti Designer插件(转载:http://blog.csdn.net/qq_33547950/article/details/54926435)

    为了完成毕业设计,需要学习Activiti.万事开头难,果然刚开始就遇到了问题.<Activiti实战>和视频教程里提供的安装Activiti Designer插件方法(即下文方法一)不能 ...

  10. 求阶乘,输入一个正整数 n,输出n!

    #include<stdio.h>int factorial (int n); int main(){ int n; scanf("%d",&n); print ...