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工作原理理解
spring的工作原理 spring是作为一个容器存在的框架,可以加载spring web,spring mvc,spring orm,sprong aop,spring dao等框架和模块,其主要核 ...
- openCV图像形态学
#include <cv.h> #include <highgui.h> #include <stdio.h> //平滑处理 int main() { IplIma ...
- Python高级入门01-property
JAVA中存在对变量 私有化,公开,保护... 私有化时候,需要提供一个公开的get 和 set方法对外公开,让别人进行调用 python中同样存在 私有化变量定义是__是这个双下划线,eg:_ ...
- mongo explain分析详解
1 为什么要执行explain,什么时候执行 explain的目的是将mongo的黑盒操作白盒化. 比如查询很慢的时候想知道原因. 2 explain的三种模式 2.1 queryPlanner 不会 ...
- 【python】-- Socket接收大数据
Socket接收大数据 上一篇博客中的简单ssh实例,就是说当服务器发送至客户端的数据,大于客户端设置的数据,则就会把数据服务端发过来的数据剩余数据存在IO缓冲区中,这样就会造成我们想要获取数据的完整 ...
- YY大厅接受不到documentcompleted事件处理
多玩大厅在接受到了页面的documentcompleted事件,才会把遮在页面前面的YY游戏中去掉,我们的游戏页面,YY大厅接收不到事件,所以就排查了下 发现原因在于js脚本里有个用iframe做上报 ...
- 洛谷 P2051 [AHOI2009]中国象棋
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- 9.Django里的数据同步migrations命令
一个关键的目录: 目录名:migrations 作用:用来存放通过makemigrations命令生成的数据库脚本,这里的内容一般不要手动去改 规定:app目录下必须要有migrations目录且目录 ...
- Java 线程的终止-interrupt
Java线程的终止——interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种 ...
- (转载)C #开源框架
Json.NET http://json.codeplex.com/ Json.Net 是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Li ...