poj1741-Tree(树的分治)
题意:给一棵树,求树上长度小于等于k的链的数量。
题解:http://blog.csdn.net/yang_7_46/article/details/9966455 照着这个博客写的代码。
不到100行,所以不应该算难吧……可是我觉得好难啊……
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int n, k;
const int N = ;
struct Edge {
int to, cost;
};
vector<Edge> g[N];
vector<int> dep; // 记录一个子树所有节点到根的距离
int sz[N]; // 记录每个子树的大小 最大子树最小的是重心
bool used[N]; // 记录每个节点是否被计算过
int minsz, root; // 重心的最大子树大小 重心
int size;
int ans;
void up(int &x, int y) { if(y>x) x=y; }
int Scan() {
int x = ; char C = getchar();
while (C < '' || C > '') C = getchar();
while (C >= '' && C <= '') { x = x * - '' + C, C = getchar(); }
return x;
}
void getroot(int u, int fa) { //找到重心
sz[u] = ;
int maxn = ;
for (unsigned i = ; i < g[u].size(); ++i) {
int v = g[u][i].to;
if (v == fa || used[v]) continue; // 因为每次都是找重心 递归求解 求过的不需要再求了
getroot(v, u);
sz[u] += sz[v];
up(maxn, sz[v]);
}
up(maxn, size-sz[u]); // size不是n 因为每次寻找的树只是一个子树
if (maxn < minsz) minsz = maxn, root = u;
}
void getdep(int u, int fa, int dis) { // 寻找子树内每一个结点到根的长度
dep.push_back(dis);
sz[u] = ;
for (unsigned i = ; i < g[u].size(); ++i) {
int v = g[u][i].to;
if (v == fa || used[v]) continue;
getdep(v, u, dis+g[u][i].cost);
sz[u] += sz[v];
}
} int cal(int u, int dis) { // dep求得u的所有子树长度,返回的是经过根节点的答案
dep.clear();
getdep(u, , dis);
sort(dep.begin(), dep.end());
int l = , r = dep.size()-;
int res = ;
while (l<r) {
if (dep[l]+dep[r] <= k) res += r-l++;
else r--;
}
return res;
} void solve(int u) { // 对于每一个结点求解 答案是经过这个结点和不经过这个结点的和
ans += cal(u, );
used[u] = true;
for (unsigned i = ; i < g[u].size(); ++i) {
int v = g[u][i].to;
if (used[v]) continue;
ans -= cal(v, g[u][i].cost); // 如果两个点位于同一棵子树会重复计算 减去
minsz = n, root = , size = sz[v]; // size的大小应该是这个子树的大小
getroot(v, );
solve(root);
}
} int main() {
while (~scanf("%d%d", &n, &k)) {
if (n == && k == ) break;
int u, v, c;
for (int i = ; i <= n; ++i) g[i].clear();
memset(used, , sizeof used);
for (int i = ; i < n; ++i) {
u = Scan(), v = Scan(), c = Scan();
g[u].push_back(Edge{v, c});
g[v].push_back(Edge{u, c});
}
minsz = n, root = , size = n;
getroot(, );
ans = ;
solve(root);
printf("%d\n", ans);
}
return ;
}
poj1741-Tree(树的分治)的更多相关文章
- [poj1741][tree] (树/点分治)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- POJ1741——Tree(树的点分治)
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...
- POJ 1741 Tree 树的分治
原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...
- POJ1741 Tree 树分治模板
http://poj.org/problem?id=1741 题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数. dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...
- poj 1741 Tree (树的分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 30928 Accepted: 10351 Descriptio ...
- POJ1741 tree 【点分治】
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 25286 Accepted: 8421 Description ...
- POJ 1741 Tree 树的分治(点分治)
题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...
- [poj1741 Tree]树上点分治
题意:给一个N个节点的带权树,求长度小于等于K的路径条数 思路:选取一个点作为根root,假设f(root)是当前树的答案,那么答案来源于两部分: (1)路径不经过root,那么就是完全在子树内,这部 ...
- E. Alternating Tree 树点分治|树形DP
题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1) 注意是点有权值. 从上头往下考虑是点分治,从下向上考虑就是树形DP, ...
- POJ1741 tree (点分治模板)
题目大意: 给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数).定义 dist(u,v)=节点 u 和 v 之间的最小距离.给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 ...
随机推荐
- 【leetcode】Longest Substring Without Repeating Characters (middle)
Given a string, find the length of the longest substring without repeating characters. For example, ...
- Codeigniter开发技巧:连接多个数据库(可实现DB读写分离)
在开发中,我们有时候会遇到在同一程序中链接多个数据库的需求,这对Codeigniter框架来说是很简单的,我们只需要在 database.php文件中配置少许参数即可. 默认情况下,CI配置的是链接一 ...
- struts2总结五: Strut2 访问Servlet API
一.间接访问 public String execute() throws Exception { this.message="hello,this is put into applicat ...
- eCos中的线程与同步
http://blog.csdn.net/ooaven/article/details/6280018 先看一下eCos线程的创建.控制以及优先级的操作这三个方面的知识,主要是对它的实现方式及API做 ...
- 基于ASP.NET的comet简单实现
http://www.cnblogs.com/hanxianlong/archive/2010/04/27/1722018.html 我潜水很多年,今天忽然出现.很久没写过博客了,不是因为不想写,而是 ...
- C++中的INL
inl文件介绍 inl文件是内联函数的源文件.内联函数通常在C++头文件中实现,但是当C++头文件中内联函数过多的情况下,我们想使头文件看起来简洁点,能不能像普通函数那样将内联函数声明和函数定义放在头 ...
- Android TextView和EditText属性详解
TextView属性详解: autoLink设置 是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none/web /email/phone/map/all) ...
- DataTable ,XML和JSON相互转化
网上搜集的,保留下来了,有需要的拿去!private string DataTable2Xml(DataTable dt) { StringBuilder xmlBuilder = new Strin ...
- windows下使用远程工具登录虚拟机上的Linux、访问虚拟机上的服务 、端口转发、win7 telnet登陆虚拟机
首先要清楚virtual box如何设置端口转发: 一篇文章: 如何使用VirtualBox进行端口转发 由于默认的方式是用NAT来做虚拟机网络的,因此如果从外网想访问虚拟机的应用会比较麻烦.以前一直 ...
- EL表达式 JSTL中的常用EL函数 动态数据的国际化
ELppt: EL 全名为Expression Language.EL主要作用: 获取数据: •EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数据.( ...