[POJ1741] Tree【树分治 点分治】
传送门:http://poj.org/problem?id=1741
写的第一道树分治题,撒花纪念~
对于每一对点对(i, j),它有三种情况:
① 其中一个是根节点。这种情况比较简单,直接加上就好了。
② 横跨根节点。这种情况是重点。
③ 不是以上两种情况。这时递归下去求解就好了。
那么对于第二种情况该怎么破呢?设根节点为root,那么dist(i, root) + dist(j, root) <= k,且需要i与j在不同的子树里。直接算不同子树的点对(i, j)的个数会麻烦,所以需要一点技巧:符合条件且在不同子树的(i, j)的对数 = 符合条件的对数 - 符合条件且在相同子树的(i, j)的对数,这样就搞定啦!
#include <cstdio>
#include <cstring>
#include <algorithm> const int maxn = 10005; int n, k, t1, t2, t3, ans;
int head[maxn], to[maxn << 1], next[maxn << 1], w[maxn << 1], lb;
int siz[maxn], a[maxn], left, right;
bool book[maxn]; inline void ist(int aa, int ss, int ww) {
to[lb] = ss;
next[lb] = head[aa];
head[aa] = lb;
w[lb] = ww;
++lb;
}
int fnd_zx(int fr, int tot_node, int p, int & rt, int & mn) {
int mx = 0;
for (int j = head[fr]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
fnd_zx(to[j], tot_node, fr, rt, mn);
mx = std::max(mx, siz[to[j]]);
}
}
mx = std::max(mx, tot_node - siz[fr]);
if (mn > mx) {
mn = mx;
rt = fr;
}
}
void get_siz(int fr, int p) {
siz[fr] = 1;
for (int j = head[fr]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_siz(to[j], fr);
siz[fr] += siz[to[j]];
}
}
}
void get_data(int r, int p, int ww) {
if (ww > k) {
return;
}
a[right++] = ww;
for (int j = head[r]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_data(to[j], r, ww + w[j]);
}
}
}
int get_ans(int l, int r) {
std::sort(a + l, a + r);
int rt = 0;
--r;
while (r > l) {
while (r > l && a[l] + a[r] > k) {
--r;
}
rt += r - l;
++l;
}
return rt;
}
void slove(int fr) {
int root = -666, mn = 2147483647;
get_siz(fr, 0);
fnd_zx(fr, siz[fr], 0, root, mn);
book[root] = true;
for (int j = head[root]; j != -1; j = next[j]) {
if (!book[to[j]]) {
slove(to[j]);
}
}
left = right = 0;
for (int j = head[root]; j != -1; j = next[j]) {
if (!book[to[j]]) {
get_data(to[j], root, w[j]);
ans -= get_ans(left, right);
left = right;
}
}
ans += get_ans(0, right) + right;
book[root] = false;
} int main(void) {
//freopen("in.txt", "r", stdin);
while (scanf("%d%d", &n, &k) && n && k) {
lb = 0;
memset(head, -1, sizeof head);
memset(next, -1, sizeof next);
ans = 0;
for (int i = 1; i < n; ++i) {
scanf("%d%d%d", &t1, &t2, &t3);
ist(t1, t2, t3);
ist(t2, t1, t3);
}
slove(1);
printf("%d\n", ans);
}
return 0;
}
[POJ1741] Tree【树分治 点分治】的更多相关文章
- POJ1741——Tree(树的点分治)
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...
- 【poj1741】Tree 树的点分治
题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...
- hdu 4812 D Tree(树的点分治)
D Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total ...
- [poj1741][tree] (树/点分治)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- POJ1741 Tree 树分治模板
http://poj.org/problem?id=1741 题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数. dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...
- POJ1741(SummerTrainingDay08-G 树的点分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 23380 Accepted: 7748 Description ...
- hdu4812-D Tree (树的点分治)
昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...
- 【POJ 1741】 Tree (树的点分治)
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...
- 树上点对统计poj1741(树的点分治)
给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
随机推荐
- Oracle 用户表空间查看、修改大小、设置自增长等
分类: Oracle 首先登入某个用户,查看某个用户在哪个表空间下: select username,default_tablespace from user_users; 查看该用户下所有的表: ...
- 【Nginx】请求上下文
上下文与全异步web服务器的关系 请求上下文指在一个请求的处理过程中,把一些关键的信息保存下来的类似struct这样的结构体.每个http模块都可以有自己的上下文结构体,一般都是在刚开始处理请求时在内 ...
- Linux 的 Socket IO 模型
前言 之前有看到用很幽默的方式讲解Windows的socket IO模型,借用这个故事,讲解下linux的socket IO模型: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系. 他 ...
- 在XX公司工作第二天,维护已有代码
根据<C++ More Exception>所述的规则: Rule #1: Never write using-directives in header files. Rule #2: N ...
- Windows server 2003 + IIS6 搭建Asp.net MVC执行环境
安装.Net Framework4.0. 下载地址: http://www.microsoft.com/zh-cn/download/details.aspx?id=17718 安装WindowsS ...
- 关于Android中物理按键不响应的可能的一个问题。
今天在工作中犯了一个错误,写的视频播放器突然物理音量键就不起作用了. 一開始以为是自己定义的音量条把系统的物理音量条按键给屏蔽掉了. 删除自己定义的音量条还是不行,又怀疑是是加入了什么权限之类的.重复 ...
- OpenGL在MFC中的使用总结(一)——基本框架
项目中要画3D显示的模型,于是要用到OpenGL,加上是在MFC中,并且是在MFC中的ActiveX中使用.再并且鉴于他们程序主框架的设定.常规的方法还不一定能实现.所以还是查过不少资料,在此一一总结 ...
- Java小白手记:SSH
以下内容只是一个小白菜鸟的理解和总结,目的仅在于梳理思路. 13年的时候,我就说要学JAVA,有个C++高手同事赞许地说:"嗯,不错,SSH..."我不禁肃然起敬.SSH!多么高大 ...
- Chapter1-data access reloaded:Entity Framework(下)
1.4 Delving deep into object/relational differences 深入挖掘对象关系的不同 理解面向对象和关系世界的不同是重要的,因为他会影响你设计一个对象模型或者 ...
- 汉诺塔算法c++源代码(递归与非递归)[转]
算法介绍: 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n - 1(有兴趣的可以自己证明试试看).后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了.首先把三根柱 ...