题目描述:

ydc有一棵n个结点的黑白相间的大树,从1到n编号。

这棵黑白树中有m个黑点,其它都是白点。

对于一个黑点我们定义他的好朋友为离他最远的黑点。如果有多个黑点离它最远那么都是它的好朋友。两点间的距离定义为两点之间的最短路的长度。

现在你要摧毁一个白点。

摧毁后有一些黑点会不高兴。一个黑点不高兴当且仅当他不能到达任何一个在摧毁那个白点前的好朋友。

请你最大化不高兴的黑点数。

解题报告:

套路题啊,直接提黑点重心到根,那么这样就可以保证每一个黑点到其最远的黑点一定经过根节点了,那么就可以开始枚举白点并讨论。

首先白点的子树内的黑点都是被截断的,然后考虑其是否在到根最长路和次长路上:

如果有三个及以上最长路显然是无法截断的。

如果仅有两个及以下,那么如果在最长路上,且最长路唯一,那么除了该子树内最长路所在子树外的所有黑点一定都能被截断。

如果是在次长路上,那么最长路上的黑点就要走到次长路上,一定会被截断

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=1e5+5;
int num=0,head[N],nxt[N<<1],to[N<<1],dis[N<<1],n,m;bool col[N];
void link(int x,int y,int z){nxt[++num]=head[x];to[num]=y;dis[num]=z;head[x]=num;}
int root=0,f[N],g[N],bel[N],sz[N];
void getroot(int x,int last,int *p){
int u;if(col[x] && p[root]<p[x])root=x;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last)continue;
p[u]=p[x]+dis[i];
getroot(u,x,p);
}
}
void dfs(int x,int last,int dist){
int u;
if(last==root)bel[x]=x;
else bel[x]=bel[last];
sz[x]=col[x];
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last)continue;
dfs(u,x,dist+dis[i]);
sz[x]+=sz[u];
}
if(sz[x]){
f[x]=dist;g[x]=1;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==last)continue;
if(f[u]>f[x]){f[x]=f[u];g[x]=g[u];}
else if(f[x]==f[u])g[x]+=g[u];
}
}
}
void work()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){scanf("%d",&x);col[x]=true;}
for(int i=1;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
link(x,y,z);link(y,x,z);
}
root=0;getroot(1,1,f);
x=root;root=0;getroot(x,x,g);
memset(f,0,sizeof(f));
getroot(root,root,f);root=0;
for(int i=1;i<=n;i++)
if(g[i]+f[i]==f[x]){
if(!root)root=i;
else if(abs(f[i]-g[i])<abs(f[root]-g[root]))root=i;
}
for(RG int i=0;i<N;i++)f[i]=g[i]=0;
dfs(root,root,0);
int mx=0,cmx=0,mxid=0,cmxid=0,ans=0,answer=0,tot=0,mxcnt=0;
if(!col[root])ans=m,answer=1;
for(int i=head[root];i;i=nxt[i]){
int u=to[i];if(!sz[u])continue;
if(f[u]>mx){cmx=mx;cmxid=mxid;mx=f[u];mxid=u;mxcnt=0;}
else if(f[u]==mx){
if(f[mxid]==f[cmxid]){mxid=0;cmxid=0;mxcnt=3;}
else{cmxid=mxid;cmx=mx;mxid=u;mx=f[u];}
}
else if(f[u]>cmx){cmxid=u;cmx=f[u];mxcnt=0;}
}
if(mxcnt==3)mxid=0,cmxid=0;
for(int i=1;i<=n;i++){
if(col[i]==1 || i==root)continue;
tot=sz[i];
if(tot && f[i]==f[bel[i]] && g[i]==g[bel[i]]){
if(bel[i]==mxid){
if(f[mxid]!=f[cmxid])tot+=m-sz[mxid];
else tot+=sz[cmxid];
}
else if(bel[i]==cmxid)tot+=sz[mxid];
}
if(tot>ans){ans=tot;answer=1;}
else if(ans==tot)answer++;
}
printf("%d %d\n",ans,answer);
}
int main(){work();return 0;}

UOJ #11. 【UTR #1】ydc的大树的更多相关文章

  1. 【UTR #1】ydc的大树

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

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

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

  3. uoj problem 11 ydc的大树

    题目大意: 给定一颗黑白树.允许删除一个白点.最大化删点后无法与删点前距自己最远的黑点连通的黑点个数.并求出方案数. 题解: 这道题很棒棒啊. 一开始想了一个做法,要用LCT去搞,特别麻烦而且还是\( ...

  4. Codeforces-348E Pilgrims

    #4342. CF348 Pilgrims 此题同UOJ#11 ydc的大树 Online Judge:Bzoj-4342,Codeforces-348E,Luogu-CF348E,Uoj-#11 L ...

  5. Codeforces 468D Tree

    题目 给出一棵带边权的树,求一个排列\(p\),使得\(\sum_{i=1}^{n}{dis(i, p_i)}\)的值最大,其中\(dis(v, u)\)表示\(v\)到\(u\)的距离. 算法 这题 ...

  6. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  7. uoj #9. 【UTR #1】vfk的数据 水题

    #9. [UTR #1]vfk的数据 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/9 Description ...

  8. UOJ #278. 【UTR #2】题目排列顺序(排序水题)

    #278. [UTR #2]题目排列顺序 丢个传送门:http://uoj.ac/problem/278 描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 U ...

  9. 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

    [UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...

随机推荐

  1. 201621123044《JAVA程序设计》第一周学习总结

    1. 本周学习总结 1.了解了JAVA的诞生以及发展历史简介.JAVA语言的特点,以及JAVA的电脑安装以及环境配置. 2.JAVA不仅可以用eclipse进行编写,也可以在记事本和notepad++ ...

  2. TOTP算法 基于时间的一次性密码

    /** Copyright (c) 2011 IETF Trust and the persons identified as authors of the code. All rights rese ...

  3. 关于GPUImage的导入

    对于GPUImage的使用方面,GitHub上已经非常详细了,就不一一赘述了,但是对于项目的导入来说,最好的方式是 1.下载GPUImage并解压 2.打开压缩包后如图 3.打开终端,cd到此目录 4 ...

  4. Struts2之Struts2的标签库

    前言: Struts2提供了大量的标签 ,用来帮助开发表现层页面,这些表现一方面解决了美观性的需求,因为它们具有html标签一样的外观,另一方面它们解决了功能性的需求, 因为它们具有jsp脚本一样的逻 ...

  5. Css之导航栏学习

    Css: ul { list-style-type:none; margin:; padding:; overflow:hidden; background-color:blue; /*固定在顶部*/ ...

  6. Python内置函数(48)——__import__

    英文文档: __import__(name, globals=None, locals=None, fromlist=(), level=0) This function is invoked by ...

  7. 关于css的层叠上下文和层叠顺序问题

    关于css的层叠上下文和层叠样式问题 最近在项目中遇到了一个让我欲仙欲死的问题,我给项目中的图片设置了一个淡入效果,几opacity变化,但当我在它的上面有一个定位元素时,动画结束后,定位元素居然被遮 ...

  8. Android 学习资料入门到精通(PDF集合)共54本

    最近收集一些安卓入门到精通,包含游戏编程,网络编程,多媒体开发,需要学习朋友就下载保持下来,下载链接在最下面 下面是网盘内容 14天学会安卓开发_(完整版).pdf Android 4  游戏高级编程 ...

  9. Linux系统的基本使用

    曾经在网上看到一个一篇文章,说到了Linux学习的入门与学习技巧,也就是:初学者可以自己安装虚拟机,然后把linux常用命令例如cd.ls.chmod.useradd.vi等等多练习几十遍,把自己敲打 ...

  10. Mybatis 中的转义字符

    记录以下mybatis中的转义字符,方便以后自己看一下 Mybatis转义字符表 < < 小于 > > 大于 & & 与 &apos; ' 单引号 &q ...