题目地址:

pid=5016">HDU 5016

先两遍DFS预处理出每一个点距近期的基站的距离与基站的编号。

然后找重心。求出每一个点距重心的距离。然后依据dis[x]+dis[y] < d[y]。用二分找出当前子树中不会被占据的数量,总点数减去即是被占据的数量。

这样就能够求出每一个点最多占据的点的数量。然后找最大值就可以。

代码例如以下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
#include <time.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
#pragma comment(linker, "/STACK:1024000000")
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=100000+10;
int head[MAXN], cnt, root, min1, tot;
int siz[MAXN], vis[MAXN], d[MAXN], id[MAXN], ans[MAXN], dis[MAXN];
int color[MAXN];
struct node
{
int v, w, next;
}edge[MAXN<<1];
void add(int u, int v, int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
struct N
{
int dis, id;
}F[MAXN];
bool cmp(N x, N y)
{
return x.dis<y.dis||(x.dis==y.dis&&x.id<y.id);
}
void init()
{
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
memset(id,0,sizeof(id));
memset(ans,0,sizeof(ans));
cnt=0;
}
void dfs1(int u, int fa)
{
if(color[u]){
id[u]=u;
d[u]=0;
}
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue ;
dfs1(v,u);
if(d[u]>d[v]+edge[i].w){
d[u]=d[v]+edge[i].w;
id[u]=id[v];
}
else if(d[u]==d[v]+edge[i].w)
id[u]=min(id[u],id[v]);
}
}
void dfs2(int u, int fa)
{
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue ;
if(d[v]>d[u]+edge[i].w){
d[v]=d[u]+edge[i].w;
id[v]=id[u];
}
else if(d[v]==d[u]+edge[i].w){
id[v]=min(id[v],id[u]);
}
dfs2(v,u);
}
}
void getsize(int u, int fa)
{
siz[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa||vis[v]) continue ;
getsize(v,u);
siz[u]+=siz[v];
}
}
void getroot(int u, int fa, int s)
{
int max1=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa||vis[v]) continue ;
getroot(v,u,s);
max1=max(max1,siz[v]);
}
max1=max(max1,s-siz[u]);
if(min1>max1){
min1=max1;
root=u;
}
}
void getdis(int u, int fa, int l)
{
dis[u]=l;
F[tot].dis=d[u]-l;
F[tot++].id=id[u];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa||vis[v]) continue ;
getdis(v,u,l+edge[i].w);
}
}
int BS(int l, int u)
{
int low=0, high=tot-1, mid, ans=-1;
while(low<=high){
mid=low+high>>1;
if(F[mid].dis<l||(F[mid].dis==l&&F[mid].id<=u)){
low=mid+1;
ans=mid;
}
else high=mid-1;
}
return ans+1;
}
void getans(int u, int fa, int f, int s)
{
int tmp=BS(dis[u],u);
ans[u]+=f*(s-tmp);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa||vis[v]) continue ;
getans(v,u,f,s);
}
}
void Cal(int u, int l, int f)
{
tot=0;
getdis(u,-1,l);
sort(F,F+tot,cmp);
getans(u,-1,f,siz[u]);
}
void work(int u)
{
vis[u]=1;
getsize(u,-1);
Cal(u,0,1);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue ;
Cal(v,edge[i].w,-1);
min1=INF;
getroot(v,u,siz[v]);
work(root);
}
}
int main()
{
int n, u, v, w, i, res;
while(scanf("%d",&n)!=EOF){
init();
for(i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
for(i=1;i<=n;i++){
scanf("%d",&color[i]);
}
dfs1(1,-1);
dfs2(1,-1);
min1=INF;
getsize(1,-1);
getroot(1,-1,n);
work(root);
res=0;
for(i=1;i<=n;i++){
if(color[i]) continue ;
res=max(res,ans[i]);
}
printf("%d\n",res);
}
return 0;
}

HDU 5016 Mart Master II (树上点分治)的更多相关文章

  1. HDU 5016 Mart Master II

    Mart Master II Time Limit: 6000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ...

  2. 【点分治】hdu5016 Mart Master II

    点分治好题. ①手动开栈. ②dp预处理每个点被哪个市场控制,及其距离是多少,记作pair<int,int>数组p. ③设dis[u].first为u到重心s的距离,dis[u].seco ...

  3. HDU - 6268: Master of Subgraph (分治+bitset优化背包)

    题意:T组样例,给次给出一个N节点的点权树,以及M,问连通块的点权和sum的情况,输出sum=1到M,用0或者1表示. 思路:背包,N^2,由于是无向的连通块,所以可以用分治优化到NlgN. 然后背包 ...

  4. hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  5. codeforces 161D Distance in Tree 树上点分治

    链接:https://codeforces.com/contest/161/problem/D 题意:给一个树,求距离恰好为$k$的点对是多少 题解:对于一个树,距离为$k$的点对要么经过根节点,要么 ...

  6. POJ 1741 Tree 树上点分治

    题目链接:http://poj.org/problem?id=1741 题意: 给定一棵包含$n$个点的带边权树,求距离小于等于K的点对数量 题解: 显然,枚举所有点的子树可以获得答案,但是朴素发$O ...

  7. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

  8. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  9. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

随机推荐

  1. [Swift通天遁地]八、媒体与动画-(15)使用TextKit实现精美的图文混排效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. Kubernetes 配置 Taint 和 Toleration(污点和容忍)

    通过污点和容忍让pod运行在特定节点上 参考官网:https://k8smeetup.github.io/docs/concepts/configuration/taint-and-toleratio ...

  3. 354 Russian Doll Envelopes 俄罗斯娃娃信封

    You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envel ...

  4. Ajax——模板引擎

    模板介绍 1.必要性:ajax请求从服务器接收到大量数据,此时再用普通的字符串拼接是很耗费时间的,这时候模板就有其必要性 2.便利性:插件套用,现在有很多主流的模板插件:BaiduTemplate(百 ...

  5. JS——百度背景图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. c++ 以二进制和以文本方式读写文件的区别

    在c++项目开发中,时常涉及到文件读写操作.因此在这里先简单梳理和回顾一下文本模式和二进制模式在进行文件读写上的区别. 1.linux平台下文本文件和二进制文件的读写 在linux平台下进行文件读写时 ...

  7. java 向上,向下转型

    在对Java学习的过程中,对于转型这种操作比较迷茫,特总结出了此文.例子参考了<Java编程思想>. 目录 几个同义词 向上转型与向下转型 例一:向上转型,调用指定的父类方法 例二:向上转 ...

  8. 搜索条件两个时间,通过php数组排序,保证select语句between时间 前小后大

    //搜索条件两个时间,通过数组排序,保证select语句between时间 前小后大 $sort_array=[$_POST['clockDate1'],$_POST['clockDate2']]; ...

  9. windows编译MaskRCNN

    1.代码修改为3.0语言版本 2.setup_windows.py 文件内容为 #!/usr/bin/env python import numpy as np import os # on Wind ...

  10. Linux 配置JDK + MyEclipse

    版本:Ubuntu16.04: jdK: Java SE Development Kit 8u102; My Eclipse: 10.6; JDK配置的细致步骤参见此处. 就一点要注意: 请使用代码进 ...