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) 顶点当且仅当 ...
随机推荐
- C++中怎么获取类的成员函数的函数指针?
用一个实际代码来说明. class A { public: staticvoid staticmember(){cout<<"static"<<endl;} ...
- POJ3034+DP
题意:给定一个N*N的矩阵, 然后在这个矩阵的每个格子在任意时间会出现一个鼹鼠,这个出现 出现鼹鼠的时间是输出信息所确定的. 现在你手里有一把锤子能够去锤这些鼹鼠. 你能 够移动锤子, ...
- 苹果p12文件--一个苹果证书怎么多次使用(蛋疼,这些问题只有和其他企业合作才会遇到,别人的账号不可能给你,蛋疼....)
在苹果开发者网站申请的证书,是授权mac设备的开发或者发布的证书,这意味着一个设备对应一个证书,但是99美元账号只允许生成3个发布证书,两个开发证书,这满足不了多mac设备的使用,使用p12文件可以解 ...
- 垃圾收集器GC的种类
堆内存的结构:
- 架构版本与 NuGet 的版本不兼容 解决方案
VS的NuGet管理在大大提高了开发效率,一直都在使用但今天在遇到了一个问题,引用一个所需要的NuGet包VS缺提示如下错误
- java高并发,如何解决,什么方式解决
之前我将高并发的解决方法误认为是线程或者是队列可以解决,因为高并发的时候是有很多用户在访问,导致出现系统数据不正确.丢失数据现象,所以想到 的是用队列解决,其实队列解决的方式也可以处理,比如我们在竞拍 ...
- fingerprintjs
Valve/fingerprintjs FingerprintJS - 在浏览器端实现指纹识别
- 在win2008中配置ServU
因为08的防火墙要求比较高.很多端口都关闭,所以要设置防火墙. 首先设置入站规则 1.新建一条规则,规则类型选择“端口”,然后TCP,设置为20-21,60010-60020,然后允许链接,在配置文件 ...
- Ejabberd源码解析前奏--调试
一.日志文件 一个ejabberd节点写两个日志文件: ejabberd.log ejabberd 服务日志, 由 ejabberd 节点汇报的消息erlang.log Erlang/OTP 系 ...
- html语意化标签
一.布局的理解误区 网络上流行管新型的布局方式叫“DIV+CSS”,其实是一个错误的理解,导致了很多人过度依赖 与滥用DIV标签, HTML提供了我们一共七八十个标签,其中常用的有三十个左右,DIV不 ...