题意:给定一个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. hadoop 启动的时候datanode报错 Problem connecting to server

    刚配置好的hadoop,namenode可以正常开启,但是datanode却不停的报错,并且不能正常启动: 2014-05-04 10:43:33,970 WARNorg.apache.hadoop. ...

  2. fedora 安装gdal

    hese steps worked for me on a Fedora system: 1.) download the 3 files related to oracle instant clie ...

  3. 添加exe为windows service服务

    [方法一] 一.介绍 srvany.exe是Microsoft Windows Resource Kits工具集的一个实用小工具,用于将EXE程序作为Windows服务运行.srvany是其注册程序的 ...

  4. 去掉tableView空白区域的分割线

    //把多余的分割线去掉 UIView * footerView = [[UIView alloc] initWithFrame:CGRectZero]; self.tableView.tableFoo ...

  5. &和&&的区别是什么

    1)&是按位与操作符,a&b是把a和b都转换成二进制数后,然后再进行按位与的运算.&&是逻辑与运算符,a&&b就是当且仅当两个操作数都为true时,其结 ...

  6. [Hbase]Hbase知识大全

    HBase简介 是一个构建在HDFS上的分布式列存储系统:HBase是基于Google BigTable模型开发的,典型的key/value系统:HBase是Apache Hadoop生态系统中的重要 ...

  7. 【UI测试】--独特性

  8. Java学习笔记:23种设计模式

    设计模式(Design pattern)的定义: In software engineering, a software design pattern is a general, reusable s ...

  9. mybatis学习 十六 auto_mapping实现连表查询

    只能使用多表联合查询方式. 要求:查询出的列别和属性名相同. 点字符  "."  在 SQL 是关键字符,两侧添加反单引号(Tab键上的一个字符) <select id=&q ...

  10. IOS 单击手势和cell点击冲突

    环境: view上添加tableView,给view添加单击手势,点击cell却走的是手势方法. 解决: UITapGestureRecognizer *tap=[[UITapGestureRecog ...