uoj problem 11 ydc的大树
题目大意:
给定一颗黑白树.允许删除一个白点.最大化删点后无法与删点前距自己最远的黑点连通的黑点个数.并求出方案数.
题解:
这道题很棒棒啊.
一开始想了一个做法,要用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的大树的更多相关文章
- uoj problem 10
uoj problem 10 题目大意: 给定任务若干,每个任务在\(t_i\)收到,需要\(s_i\)秒去完成,优先级为\(p_i\) 你采用如下策略: 每一秒开始时,先收到所有在该秒出现的任务,然 ...
- Problem 11
Problem 11 # Problem_11.py """ In the 20×20 grid below, four numbers along a diagonal ...
- 【UTR #1】ydc的大树
[UTR #1]ydc的大树 全网唯一一篇题解我看不懂 所以说一下我的O(nlogn)做法: 以1号点为根节点 一个黑点如果有多个相邻的节点出去都能找到最远的黑点,那么这个黑点就是无敌的 所以考虑每个 ...
- UOJ #11. 【UTR #1】ydc的大树
题目描述: ydc有一棵n个结点的黑白相间的大树,从1到n编号. 这棵黑白树中有m个黑点,其它都是白点. 对于一个黑点我们定义他的好朋友为离他最远的黑点.如果有多个黑点离它最远那么都是它的好朋友.两点 ...
- UOJ #11 - 【UTR #1】ydc的大树(换根 dp)
题面传送门 Emmm--这题似乎做法挺多的,那就提供一个想起来写起来都不太困难的做法吧. 首先不难想到一个时间复杂度 \(\mathcal O(n^2)\) 的做法:对于每个黑点我们以它为根求出离它距 ...
- leetcode problem 11 Container With Most Water
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). ...
- uoj problem 31 猪猪侠再战括号序列
题目大意: 给定一个长度为2n的括号序列.定义一个关于区间[l,r]的翻转操作为位置平移对调. 即翻转")))()("可以得到"()()))((" 用不超过n次 ...
- uoj problem 14 DZY Loves Graph
题目: DZY开始有 \(n\) 个点,现在他对这 \(n\) 个点进行了 \(m\) 次操作,对于第 \(i\) 个操作(从 \(1\) 开始编号)有可能的三种情况: Add a b: 表示在 \( ...
- uoj problem 21 缩进优化
题目: 小O是一个热爱短代码的选手.在缩代码方面,他是一位身经百战的老手.世界各地的OJ上,很多题的最短解答排行榜都有他的身影.这令他感到十分愉悦. 最近,他突然发现,很多时候自己的程序明明看起来比别 ...
随机推荐
- spring boot数据库操作汇总
1 关于orm orm即object relational mapping,对象关系映射,即将数据库中的表映射成对象. 常用的orm有以下: mybatis spring jdbc template ...
- How to avoid Over-fitting using Regularization?
http://www.mit.edu/~9.520/scribe-notes/cl7.pdf https://en.wikipedia.org/wiki/Bayesian_interpretation ...
- Python菜鸟之路:前端HTML基础
前面的章节中,Python的基本知识已经差不多介绍完了.本节介绍HTML相关的知识.需要着重声明的是,前端知识是非常非常重要的知识,以我实际项目经验来看,一个项目的瓶颈在设计和前端.设计就先不说了,前 ...
- 基于flask的web微信
web微信 1.扫码获取头像 当你打开web微信的时候,因为http是无状态的,web微信如何实时的获取用户的扫码动作? 那么这里用到的是长轮询的方式. from flask import Flask ...
- Alex 的 Hadoop 菜鸟教程: 第2课 hadoop 安装教程 (CentOS6 CDH分支 yum方式)
原帖地址:http://blog.csdn.net/nsrainbow/article/details/36629339 我们这个教程是在 centos 上安装cdh的教程,并且使用的是yum方式. ...
- 打开或者 关闭 php 的错误报告
一般线上的环境,我会 php的报错信息屏蔽掉,php.ini 设置的办法 如下: display_errors = Off error_reporting = E_ALL 在代码中,可以这样~~: e ...
- C#聚合运算方法
Aggregate 对集合值执行自定义聚合运算 Average 计算集合平均值 Count 对集合的元素惊醒计数,还可以仅对满足某一谓词函数的元素进行计数 LongCount 对大型集合中的元素进行计 ...
- 内存写越界导致破环堆结构引起的崩溃问题定位经验[如报错malloc(): memory corruption或free(): invalid next size]
前段时间开发的一个后端C模块上线后,线上出core,初始时,因为訪问压力不大,所以崩溃是上线3天左右出现的.当时用gdb跟进调用堆栈并检查源代码,发现出core位置的代码沒有啥问题.因为当时开发任务较 ...
- linux sort按照指定列排序
sort怎样按指定的列排序0000 27189 41925425065f 15 419254250663 7 419254250675 5 419254250691 76 419254250693 2 ...
- 算法(Algorithms)第4版 练习 1.3.42
After copy Left on Stack r: be to not or be to Left on Stack copy: be to not or be to After r pop Le ...