POJ 1741 Tree (树分治入门)
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 8554 | Accepted: 2545 |
Description
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The last test case is followed by two zeros.
Output
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
Source
可以看论文。
讲得很明白了。
写分治主要是合并的过程。
/* ***********************************************
Author :kuangbin
Created Time :2013-11-17 14:30:29
File Name :E:\2013ACM\专题学习\树的分治\POJ1741.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MAXN = ;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,next,w;
}edge[MAXN*];
int head[MAXN],tot;
void init()
{
tot = ;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[tot].to = v; edge[tot].w = w;
edge[tot].next = head[u];head[u] = tot++;
}
bool vis[MAXN];
int size[MAXN],dep[MAXN];
int le,ri;
int dfssize(int u,int pre)
{
size[u] = ;
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre || vis[v])continue;
size[u] += dfssize(v,u);
}
return size[u];
}
int minn;
//找重心
void getroot(int u,int pre,int totnum,int &root)
{
int maxx = totnum - size[u];
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre || vis[v])continue;
getroot(v,u,totnum,root);
maxx = max(maxx,size[v]);
}
if(maxx < minn){minn = maxx; root = u;}
}
void dfsdepth(int u,int pre,int d)
{
dep[ri++] = d;
for(int i = head[u];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(v == pre || vis[v])continue;
dfsdepth(v,u,d+edge[i].w);
}
}
int k;
int getdep(int a,int b)
{
sort(dep+a,dep+b);
int ret = , e = b-;
for(int i = a;i < b;i++)
{
if(dep[i] > k)break;
while(e >= a && dep[e] + dep[i] > k)e--;
ret += e - a + ;
if(e > i)ret--;
}
return ret>>;
}
int solve(int u)
{
int totnum = dfssize(u,-);
int ret = ;
minn = INF;
int root;
getroot(u,-,totnum,root);
vis[root] = true;
for(int i = head[root];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(vis[v])continue;
ret += solve(v);
}
le = ri = ;
for(int i = head[root];i != -;i = edge[i].next)
{
int v = edge[i].to;
if(vis[v])continue;
dfsdepth(v,root,edge[i].w);
ret -= getdep(le,ri);
le = ri;
}
ret += getdep(,ri);
for(int i = ;i < ri;i++)
{
if(dep[i] <= k)ret++;
else break;
}
vis[root] = false;
return ret;
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
int u,v,w;
while(scanf("%d%d",&n,&k) == )
{
if(n == && k == )break;
init();
for(int i = ;i < n;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
memset(vis,false,sizeof(vis));
printf("%d\n",solve());
}
return ;
}
POJ 1741 Tree (树分治入门)的更多相关文章
- POJ 1741 Tree 树分治
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- poj 1741 Tree (树的分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 30928 Accepted: 10351 Descriptio ...
- poj 1744 tree 树分治
Tree Time Limit: 1000MS Memory Limit: 30000K Description Give a tree with n vertices,each ed ...
- POJ 1741 Tree ——点分治
[题目分析] 这貌似是做过第三道以Tree命名的题目了. 听说树分治的代码都很长,一直吓得不敢写,有生之年终于切掉这题. 点分治模板题目.自己YY了好久才写出来. 然后1A了,开心o(* ̄▽ ̄*)ブ ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
- POJ 1741 Tree 树的分治
原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...
- Tree POJ - 1741【树分治】【一句话说清思路】
因为该博客的两位作者瞎几把乱吹(" ̄︶ ̄)人( ̄︶ ̄")用彼此的智慧总结出了两条全新的定理(高度复杂度定理.特异根特异树定理),转载请务必说明出处.(逃 Pass:anuonei, ...
- POJ 1741 Tree 树的分治(点分治)
题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...
- POJ 1741 Tree(点分治点对<=k)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
随机推荐
- CSS background汇总
本文更新版本 ,请跳转 所有背景属性都不能继承. 1. background-color 所有元素都能设置背景颜色. background-color的默认值是transparent:也就是说, ...
- Dream------Hadoop--网络拓扑与Hadoop--摘抄
两个节点在一个本地网络中被称为“彼此的近邻”是什么意思?在高容量数据处理中,限制因素是我们在节点间 传送数据的速率-----带宽很稀缺.这个想法便是将两个节点间的带宽作为距离的衡量标准. 衡量节点 ...
- 安装asp.net mvc4后mvc3项目编译报错
安装asp.net mvc4之后,之前的mvc3项目编译时报这个错“The type System.Web.Mvc.ModelClientValidationRule exists in both c ...
- tar.gz tar.bz2的解压命令
.tar.gz 格式解压为 tar -zxvf xx.tar.gz .tar.bz2 格式解压为 tar -jxvf xx.tar.b ...
- Windows下安装Python及Eclipse中配置PyDev插件
最近开始接触Python,鉴于之前安装Java的教训,决定这次边安装Python,边写下历程,供日后反复使用. 在Python官网http://www.python.org/下载Python版本,鉴于 ...
- jenkins 使用Git持续构建
为jenkins添加git插件. 在Available tab页中找到Git Plugin 点击下方的Install without Restart安装插件. 插件安装完毕后,我们需要在jenkins ...
- 输出联系变化的数字seq
主要作用:输出联系变化的数字格式:Seq 分割符号 开始 间隔 结束开始默认是1,间隔默认是1,分隔符默认回车一位是结束,两位首末,三位首间隔末,没有四位,开始可以是负数主要参数:-f 指定格式打印- ...
- c++中的类(class)
c++的class(类)使用方法 这几天一直在调splay之类的东西,突然想转指针...qwq 于是,我就在沙华大佬的帮助下,学了下一顿乱指( $ -> $ ),也就是class(类) 首先:c ...
- ERP客户关系渠管理添加和修改联系人(二十一)
树形结构treeview 前端代码: <form id="form1" runat="server"> <div> <asp:Tr ...
- php中empty()、isset()、is_null()和变量本身的布尔判断区别
<?php//预定义变量数组:空字符,字符0,数组0,null,布尔false,空数组$arr_var = array('', '0', 0, null, false, array()); fo ...