题意:给定一个n个点的图,这个图是一棵树,然后有些点建立了集市。并且没有集市的地方去集市一定是去最近的,如果距离相同,那么则去标号最小的。。现在你还能在建一个集市,问建完这个集市最多有多少个点来这里。。

思路:

现对于每个点求该点到有标记点最近的距离,记录距离及其最近标号,可以用树形dp或者spfa搞。。

然后我们任意选定一个点建树,建完后进行点分治。。

对于当前分治快的跟rt,求rt到每个点的距离为dis,near为到标记点最近的距离

那么对于不同子树的点u,v,如果dis[u] + dis[v] < near[v],那么如果u建立集市v肯定到u。。

那么我们把式子变形下,dis[u] < near[v] - dis[v],对于u直接二分查找统计即可。。

我们可以先不管哪棵子树先统计一边,然后再减去相同的即可,这样写起来方便点。。写起来还蛮像poj1741的。。

code:

 /*
* Author: Yzcstc
* Created Time: 2014/10/2 17:37:34
* File Name: hdu5016.cpp
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define M0(x) memset(x, 0, sizeof(x))
#define clr(x, y) memset(x, y, sizeof(x))
#define N 120000
#define Inf 0x3fffffff
#define x first
#define y second
using namespace std;
typedef pair<int, int> pii;
struct edge{
int v, w, next;
edge(){}
edge(int _v, int _w, int _next):v(_v), w(_w), next(_next){}
} e[N<<];
int last[N], n, len, have[N], ans[N];
int inq[N];
pii ner[N]; void add(int u, int v, int w){
e[len] = edge(v, w, last[u]), last[u] = len++;
} void init(){
clr(last, -);
len = ;
int u, v, w;
for (int i = ; i < n; ++i){
scanf("%d%d%d", &u, &v, &w);
add(u, v, w), add(v, u, w);
}
repf(i, , n) scanf("%d", &have[i]);
} void gao(){
repf(i, , n) ner[i].x = ner[i].y = Inf, inq[i] = ;
queue<int> q;
repf(i, , n) if (have[i]){
ner[i].x = , ner[i].y = i;
q.push(i), inq[i] = ;
}
int u, v;
pii tmp;
while (!q.empty()){
u = q.front();
q.pop(), inq[u] = ;
for (int p = last[u]; ~p; p = e[p].next){
v = e[p].v;
tmp.x = ner[u].x + e[p].w, tmp.y = ner[u].y;
if (tmp < ner[v]){
ner[v] = tmp;
if (!inq[v]) inq[v] = , q.push(v);
}
}
} }
/*** 点分治-begin **/
int vis[N], sz, msize[N], f[N], size[N], belong[N], ss, ff[N];
int dis[N];
pair<int, int> s[N], tp; void dfs(int u, int fa){ //calculate the size
f[sz++] = u;
msize[u] = , size[u] = ;
int v;
for (int p = last[u]; ~p; p = e[p].next){
v = e[p].v;
if (v == fa || vis[v]) continue;
dfs(v, u);
size[u] += size[v];
msize[u] = max(size[v], msize[u]);
}
} void dfs(int u, int fa, int dist){
dis[u] = dist, ff[ss++] = u;
int v;
for (int p = last[u]; ~p; p = e[p].next){
v = e[p].v;
if (v == fa || vis[v]) continue;
dfs(v, u, dist + e[p].w);
}
} void calculate(int u, int dist){
ss = ;
dfs(u, , dist);
for (int i = ; i < ss; ++i)
s[i].x = ner[ff[i]].x - dis[ff[i]], s[i].y = ner[ff[i]].y;
sort(s, s+ss);
int t;
for (int i = ; i < ss; ++i) if (!have[ff[i]]){
tp.x = dis[ff[i]], tp.y = ff[i];
t = lower_bound(s, s+ss, tp) - s;
ans[ff[i]] += (dist > ) ? (t - ss) : (ss - t);
}
} void dfs(int u){
sz = ;
dfs(u, );
int rt = , tmp, v;
for (int i = ; i < sz; ++i){
tmp = max(msize[f[i]], sz--size[f[i]]);
if (tmp <= (sz>>)) { rt = f[i]; break; }
}
calculate(rt, );
vis[rt] = ;
for (int p = last[rt]; ~p; p = e[p].next){
v = e[p].v;
if (vis[v]) continue;
calculate(v, e[p].w);
dfs(v);
}
}
/**** 点分治-end***/ void solve(){
gao();
M0(vis);
M0(ans);
dfs();
int mx = ;
for (int i = ; i <= n; ++i)
mx = max(ans[i], mx);
printf("%d\n", mx);
} int main(){
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
while (scanf("%d", &n) != EOF){
init();
solve();
}
return ;
}

hdu5016的更多相关文章

  1. 【点分治】hdu5016 Mart Master II

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

  2. Bryce1010 Acm模板

    目录 STL标准模板库 STL简介 STL pair STL set STL vector STL string STL stack STL queue STL map upper_bound和low ...

随机推荐

  1. MacDev.GarbageCollectionIsDeprecated-WhenXcodeCompileMacAppProject

    Garbage Collection is not supported 当Xcode编译Mac OSX App时报错:"Garbage Collection is not supported ...

  2. How to Solve Lonsdor K518ISE Abnormal Display by Factory Resetting

    Here’s the working solution to Lonsdor K518ISE Key Programmer abnormal display after upgrade. Proble ...

  3. 10. pt-fk-error-logger

    pt-fk-error-logger DSN 外键约束相关的,不关注.

  4. VS2010工程结构及其瘦身策略

    VS2010工程结构: 我们以在VS2010上利用MFC创建的单文档应用程序HelloWorld的文件结构为例,简述VS2010应用程序工程中文件的组成结构. 1.解决方案相关文件 解决方案相关文件包 ...

  5. c++文件中引用C代码

    下面提供一个比较完整的示例程序,一共有四个文件:main.cpp.test.c.test.h.test.hpp main.cpp #include "test.hpp" int m ...

  6. 存储过程和函数 PROCEDURE & FUNCTION

    SQL语句执行的时候,要首先编译,然后在被执行.在大型数据库系统中,为了提高效率,将为了完成特定功能的SQL语句集进行编译优化后,存储在数据库服务器中,用户通过指定存储过程的名字来调用执行. 具体而言 ...

  7. 新手必看,史上最全的iOS开发教程集锦,没有之一!

    最近大火的iPhone XS Max和iPhone XS,不知道有没有同学已经下手了呢?一万三的价位确实让很多人望而却步啊.据说为了赢得中国的用户,专门出了双卡双待的,可想而知中国市场这块“肥肉”人人 ...

  8. SQL Server 查询中文字段返回为空

    昨晚维护系统数据时,遇到个奇怪现象.明明数据库里有数据,查询结果就是返回为空.具体情况是这样的,查询工作日志表里关于工作描述的情况,以中文内容匹配工作描述字段,其中匹配内容里包含有空格. 尝试去掉第一 ...

  9. Maven中maven-source-plugin,maven-javadoc-plugin插件的使用

    摘要:今天领导说要把项目通过maven生产源码包和文档包并发布到自己的私服上,经过查看mavne官网发现有两个maven插件可以做到这些工作,一个是maven-source-plugin,另一个是ma ...

  10. Reduce 和 Transduce 的含义

    一.reduce 的用法 reduce是一种数组运算,通常用于将数组的所有成员"累积"为一个值. var arr = [1, 2, 3, 4]; var sum = (a, b) ...