[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 ...
随机推荐
- ArcGIS Engine 中的多线程使用
转自原文ArcGIS Engine 中的多线程使用 一直都想写写AE中多线程的使用,但一直苦于没有时间,终于在中秋假期闲了下来.呵呵,闲话不说了,进入正题! 大家都了解到ArcGIS中处理大数据量时速 ...
- [Rust] Setup Rust for WebAssembly
In order to setup a project we need to install the nightly build of Rust and add the WebAssembly tar ...
- VC++ error C1083 无法打开包括文件 fstream.h,iostream.h怎么办
1 如下图所示,VS中不支持iostream.h和fstream.h的说法 2 改成下面三行就可以编译通过了 #include<iostream> #include <fstre ...
- Microduino-W5500
2014-06-13, Microduino 公布了全新的以太网模块Microduino-W5500 ,模块基于WIZnet以太网芯片,拥有独特的全硬件TCP/IP协议栈. attachment_id ...
- Ubuntu16.04下安装Tensorflow CPU版本(图文详解)
不多说,直接上干货! 推荐 全网最详细的基于Ubuntu14.04/16.04 + Anaconda2 / Anaconda3 + Python2.7/3.4/3.5/3.6安装Tensorflow详 ...
- thinkphp3.2.3 数据库写入add 方法的一些问题。
最近在做项目中遇到的一个数据操作add()方法,在不开启debug的模式下会漏掉一些字段没写入数据库. 当时并不知道是这个原因,明明在开发的时候都是没问题的,怎么突然出现这个问题,找了好久都没有头绪, ...
- 用bis和bic实现位级操作
20世纪70年代末至80年代末,DigitalEquipment的VAX计算机是一种非常流行的机型.它没有布尔运算AND和OR指令,仅仅有bis(位设置)和bic(位清除)这两种指令.两种指令的输入都 ...
- TCP/IP具体解释--TCP/IP可靠的原理 滑动窗体 拥塞窗体
TCP和UDP处在同一层---运输层,可是TCP和UDP最不同的地方是,TCP提供了一种可靠的数据传输服务,TCP是面向连接的,也就是说,利用TCP通信的两台主机首先要经历一个"拨打电话&q ...
- 在Android用ZXing.jar识别二维码的精简版(简化了配置和代码)
近期公司做了一款OTP令牌激活的产品,因为之前激活手机令牌须要输入非常多的激活信息才干进行激活. 经过一段使用后,发现易用性不是非常强,考虑假设添加二维码的的扫码功能岂不是大大添加了易 ...
- HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) ...