题目描述:

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. 第一部分 linux系统命令

    一.linux系统命令 pwd 当前目录位置 / 根目录 cd (change direcory) cd ..返回上一层目录 ls 显示当前目录下文件 ls -l 显示目录下详细文件信息 ls -lh ...

  2. EasyUI导航栏。

    html: <div data-options="region:'west',split:true" title="导航栏菜单" style=" ...

  3. 彻底搞懂shell的高级I/O重定向

    本文目录: 1.1 文件描述符(file description,fd) 1.2 文件描述符的复制 1.3 重定向顺序很重要:">file 2>&1"和&quo ...

  4. 常用的汇编指令 movs stos

    movsb   把寄存机esi所存的地址的数据以字节复制到edi movsw  把寄存机esi所存的地址的数据以word复制到edi movsd   把寄存机esi所存的地址的数据以dword复制到e ...

  5. c# aynsc 和 await

      static void Main(string[] args) { Print(); Console.WriteLine("这是主线程"); } public static a ...

  6. jquery 实时监听输入框值变化方法

    $('.offers-number').bind('input propertychange', function (a, b) { var value = $(this).val() if (!va ...

  7. angular2 学习笔记 ( 状态管理 state management )

    更新 : 2017-12-29  ng5 移除 zone.js https://zhuanlan.zhihu.com/p/29577461 zone 的用途就是拦截游览器事件, 比如 click, a ...

  8. 从零搭建 webpack3 环境 #1 - 安装使用

    目录: (1)什么是webpack (2)webpack核心概念 (3)环境安装 (4)开始使用webpack 1.什么是webpack 官网的一幅图对webpack的解释,从图中可以看出,webpa ...

  9. leetcode算法: Find Bottom Left Tree Value

    leetcode算法: Find Bottom Left Tree ValueGiven a binary tree, find the leftmost value in the last row ...

  10. JavaScript 评论添加练习

    JavaScript 评论添加练习 本次所学内容: //var str = '<li>'+value+'</li>'; 支付串和变量的拼接 //ul.innerHTML += ...