题目地址:

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. [Luogu 1052] noip 05 过河

    [Luogu 1052] noip 05 过河 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是 ...

  2. 题解报告:hdu 2647 Reward(拓扑排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647 Problem Description Dandelion's uncle is a boss ...

  3. OFDM同步算法之Park算法

    park算法代码 训练序列结构 T=[\(C\) \(D\) \(C^{*}\) \(D^{*}\)],其中C表示由长度为N/4的复伪随机序列PN,ifft变换得到的符号序列 \(C(n) = D(N ...

  4. OpenCV绘制检测结果

    OpenCV绘制检测结果 opencv  rtcp  timestamp  一.介绍 由于在验证阶段,使用FPGA时我们的算法检测速度很慢,没法直接在主流上进行绘图,否则的话,主流就要等待算法很久才能 ...

  5. node 搭建本地服务器

    /** * 代理服务器 natapp -authtoken f1bdaa0535788971 * 热部署指令 supervisor index */ const Koa = require('koa' ...

  6. R 连接数据库长数字被科学计数法解决方法

    数据库中的订单编号

  7. Lvs Keepalive DR模式高可用配置

    Lvs Keepalive DR模式配置 一.环境 #DIP# eth0:192.168.233.145#VIP# eth0:0 192.168.233.250/32 #RIP1:192.168.23 ...

  8. Centos7 Openstack - (第二节)添加认证服务(Keystone)

    Centos7 install Openstack - (第二节)添加认证服务(Keystone) 我的blog地址:http://www.cnblogs.com/caoguo 根据openstack ...

  9. jenkins配置发送测试结果邮件

    简单版: https://www.cnblogs.com/gcgc/p/5631385.html https://blog.51cto.com/qicheng0211/1919341 升级版 http ...

  10. CAD绘制一个角度标注(com接口VB语言)

    主要用到函数说明: _DMxDrawX::DrawDimAngular 绘制一个角度标注.详细说明如下: 参数 说明 DOUBLE dAngleVertexX 角度标注的顶点的X值 DOUBLE dA ...