hdu5016
题意:给定一个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的更多相关文章
- 【点分治】hdu5016 Mart Master II
点分治好题. ①手动开栈. ②dp预处理每个点被哪个市场控制,及其距离是多少,记作pair<int,int>数组p. ③设dis[u].first为u到重心s的距离,dis[u].seco ...
- Bryce1010 Acm模板
目录 STL标准模板库 STL简介 STL pair STL set STL vector STL string STL stack STL queue STL map upper_bound和low ...
随机推荐
- hdu 1754(基础线段树) I Hate It
http://acm.hdu.edu.cn/showproblem.php?pid=1754 数据比较大,暴力会超时,所以明显是线段树,普通的线段树,结构体中多开一个值sum储存每个子区间的最大成绩, ...
- 找不到或无法加载主类(Could not find or load main class )
在Linux环境下,写了一个简单的java程序,通过javac编译成class文件,然后用java 运行的时候,报了这个错误, 搜了一下,可能是classpath的问题,所以用echo $CLASSP ...
- python面向对象的三大特征
1.封装: 封装就是对类和对象的成员访问进行限制,设定可以访问的方式和不可以访问的方式. 分类: 私有化的封装:当前类/对象种可以使用,类/对象外和子类/对象都不可以用 受保护的封装:当前类/对象和子 ...
- Expressions入门示例
学习表达式的入门例子,前提是要对委托有一定的了解,泛型明白一些.using System; using System.Linq; using System.Linq.Expressions; usin ...
- VS2010正则批量替换set_和get_
批量替换set_: daohang.set_ChannelName(rowArray[0]["ChannelName"].ToString()); daohang.set_Chan ...
- Spring MVC 中的 forward redirect Flash属性
forward:转发 redirect:重定向 -- 转发比重定向快,因为重定向经过客户端,而转发并没有. -- 重定向能够重定向到一个外部网站,但转发不行. -- 重定向能够避免在用户重新加载页面时 ...
- SQL截取字符串分隔符中间部门的办法
需求:实际项目中需要截取第2到第3个逗号中间部分的内容 方案: declare @str nvarchar(50);set @str='11,222,3333,44444';select @str a ...
- centos 6.5 搭建zookeeper集群
为什么使用Zookeeper? 大部分分布式应用需要一个主控.协调器或控制器来管理物理分布的子进程(如资源.任务分配等)目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制协调程序的反复编写浪费 ...
- python上下文管理协议
所谓上下文管理协议,就是咱们打开文件时常用的一种方法:with __enter__(self):当with开始运行的时候触发此方法的运行 __exit__(self, exc_type, exc_va ...
- Twitter 相关APP开发
首先要获取 Consumer Key (API Key), Consumer Secret (API Secret):最好申请Access Token 和Access Token Secret,不然验 ...