题目描述:

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. TSP-旅行商问题

    #include <iostream> #include <vector> #include <algorithm> using namespace std; in ...

  2. (原创)不带模板的OLE输出EXCEL

    目前我已知的EXCEL输出方式有3种: 1.GUI_DOWNLOAD函数输出(适用于简单无格式要求的输出). 2.OLE输出(适用于对EXCEL格式输出有特殊要求的,但是因其填充数据和设置格式是基于一 ...

  3. python全栈开发-Day13 内置函数

    一.内置函数 注意:内置函数id()可以返回一个对象的身份,返回值为整数. 这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以 ...

  4. Linux下高效指令

    Linux管理磁盘 资本指令 查看当前磁盘使用情况:df -h fdisk -l (查看所有的硬盘) 服务器添加硬盘:在系统设置添加 分区: fdisk /dev/sdb (sdb, sdc, sde ...

  5. LeetCode & Q27-Remove Element-Easy

    Array Two Pointers Description: Given an array and a value, remove all instances of that value in pl ...

  6. 读论文系列:Object Detection ECCV2016 SSD

    转载请注明作者:梦里茶 Single Shot MultiBox Detector Introduction 一句话概括:SSD就是关于类别的多尺度RPN网络 基本思路: 基础网络后接多层featur ...

  7. emqtt 试用(二)验证 emq 和 mosquito 的共享订阅

    本地订阅(Local Subscription) 本地订阅(Local Subscription)只在本节点创建订阅与路由表,不会在集群节点间广播全局路由,非常适合物联网数据采集应用. 使用方式: 订 ...

  8. Linux知识积累 (9) 创建用户、分配权限和更改所有者

    一.useradd和adduser 1.useradd命令: 用于Linux中创建的新的系统用户. useradd可用来建立用户帐号.帐号建好之后,再用passwd设定帐号的密码. 而可用userde ...

  9. SpringCloud的部署模型

    http://www.th7.cn/Program/java/201608/919853.shtml

  10. Python大婶博客汇总

    Python大神金星 博客:http://www.cnblogs.com/jin-xin/articles/7459977.html