http://blog.csdn.net/woshi250hua/article/details/7723400

求两点间距离小于等于k的方案数

理一下思路:

求通过点A与另一点连接符合条件的个数 = 到点A距离相加符合条件个数 - A内部符合条件的个数

步骤:

因为从哪个点开始都一样,所以每次找子树重心开始遍历

求出子节点到这个点的所有距离,排序搜索,得出总方案数

减掉内部符合条件的数量,得到通过这个点的方案数

以此遍历每个点

注意:

求重心时,因为每次子树数量都是不一样的,要动态更新

相向搜索:O(n)

sort(dis,dis+tot);
int left =,right = tot-;
while(left<right)
{
if(dis[left]+dis[right]<=k)
{
ans-= right-left;
left++;
}
else right--;
}

AC代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std; #define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 20000+5
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f #define ls (rt<<1)
#define rs (rt<<1|1) int n,m,k; int ptr = ,head[MAXN],vis[MAXN]; int num,ans,tot,rt,sum,son[MAXN],dis[MAXN],mu[MAXN]; struct node
{
int y,val,next;
}tree[MAXN<<]; void add(int fa,int son,int val)
{
tree[ptr].y = son;
tree[ptr].val = val;
tree[ptr].next = head[fa];
head[fa] = ptr++;
} void getroot(int root,int fa)
{
son[root] = ;
int tmp = ;
for(int i=head[root];i!=-;i=tree[i].next)
{
int y = tree[i].y;
if(vis[y] || y == fa) continue;
getroot(y,root);
son[root] += son[y];
tmp = max(son[y],tmp);
mu[root] = max(mu[root],son[y]);
}
tmp = max(tmp,sum-son[root]);
if(tmp<num)
{
num = tmp;
rt = root;
}
} void getdis(int root,int fa,int dist)
{
dis[tot++] = dist;
for(int i=head[root];i!=-;i=tree[i].next)
{
int y = tree[i].y;
if(vis[y] || y == fa || dist+tree[i].val > k) continue;
getdis(y,root,dist+tree[i].val);
}
} void getcnt()
{
sort(dis,dis+tot);
int left =,right = tot-;
while(left<right)
{
if(dis[left]+dis[right]<=k)
{
ans+= right-left;
left++;
}
else right--;
}
} void getcnt2(int root)
{
vis[root] = ;
for(int i=head[root];i!=-;i=tree[i].next)
{
int y = tree[i].y;
if(vis[y]) continue;
tot = ;
getdis(y,root,tree[i].val);
sort(dis,dis+tot);
int left =,right = tot-;
while(left<right)
{
if(dis[left]+dis[right]<=k)
{
ans-= right-left;
left++;
}
else right--;
}
}
} void solve(int root,int fa)
{
num = sum = son[root];
getroot(root,fa);
tot = ;
getdis(rt,,);
getcnt();
getcnt2(rt);
for(int i=head[rt];i!=-;i=tree[i].next)
{
int y = tree[i].y;
if(vis[y] || y==fa) continue;
solve(y,rt);
}
} int main()
{
int i,j,t,kase=;
while(~sf("%d%d",&n,&k),n+k)
{
mem(tree,);
mem(head,-);
mem(vis,);
mem(dis,);
ans = ;
ptr = ;
son[] = n;
int x,y,z;
for(i=;i<n;i++)
{
sf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
solve(,);
pf("%d\n",ans);
}
return ;
}
/*
5 3
1 2 1
2 3 1
3 4 1
4 5 1
*/

poj 1741 两点距离小于K(树DP)的更多相关文章

  1. poj 1987 节点距离小于等于K(树DP)

    这题和poj 1741是一模一样的 但是1741能AC的代码,在这里却是TLE,暂时没看出哪里出现了问题.. AC代码: #include <iostream> #include < ...

  2. Life Forms POJ - 3294(不小于k个字符串中的最长子串)

    题意: 求不小于字符串一半长度个字符串中的最长字串 解析: 论文题例11 将n个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开, 求后缀数组, 然后二分答案变为判定性问题, 然后判断每组的 ...

  3. Common Substrings POJ - 3415(长度不小于k的公共子串的个数)

    题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1  sa[i] < len1  和  sa[i-1] < ...

  4. [51NOD1405] 树的距离之和(树DP)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405 (1)我们给树规定一个根.假设所有节点编号是0-(n-1 ...

  5. POJ 1741 Tree 树形DP(分治)

    链接:id=1741">http://poj.org/problem?id=1741 题意:给出一棵树,节点数为N(N<=10000),给出N-1条边的两点和权值,给出数值k,问 ...

  6. POJ - 1741 Tree

    DescriptionGive a tree with n vertices,each edge has a length(positive integer less than 1001).Defin ...

  7. POJ 1741 Tree 求树上路径小于k的点对个数)

                                                                                                 POJ 174 ...

  8. 树的点分治 (poj 1741, 1655(树形dp))

    poj 1655:http://poj.org/problem?id=1655 题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...

  9. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

随机推荐

  1. Sum of LCM (lcmsum)

    题目 [题目描述] 对于 $ A_1, A_2, \ldots, A_N $ ,求$\sum_{i = 1}^N \sum_{j = 1}^N \mathrm{lcm}(A_i, A_j)$ 的值. ...

  2. Jmeter处理cookie

    修改bin/jmeter.properties中的 保存后重启jmeter 在测试计划中添加HTTP Cookie 管理器

  3. 背包 DP【洛谷P4158】 [SCOI2009]粉刷匠

    P4158 [SCOI2009]粉刷匠 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上 ...

  4. luogu2948 滑雪课

    题解里面全是dp的大神本蒟蒻瑟瑟发抖奉上一篇记忆化搜索... 其实嘛,记忆化搜索还是很安全透彻清真人品的,一般递推不好实现dp可以用记忆化搜索 然后本题先预处理一个mint[i]代表当前能力值为i,参 ...

  5. springcloud系列九 整合Hystrix Dashboard

    Hystrix Dashboard是Hystrix的仪表盘组件,主要用来实时监控Hystrix的各项指标信息,通过界面反馈的信息可以快速发现系统中存在的问题. 整合快速体验: pom.xml(这个是F ...

  6. SprimgMVC学习笔记(六)—— 全局异常的处理

    一.处理思路 springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 系统中异常包括两类:预期异常和运行时异常RuntimeExcept ...

  7. Luogu P5122 [USACO18DEC]Fine Dining 最短路

    先跑一遍n为起点最短路,再新开一个点,向有干草垛的点连一根边权为d[u]-w的有向边(很重要..我当时连的无向边,然后我死了.),相当于用价值抵消一部分边权, 然后以这个新的点为起点跑最短路就好了.. ...

  8. P2575 高手过招

    传送门 直接搞好像搞不了 考虑转换模型 显然每一行棋子不会跑到其他行.. 所以可以把每一行的情况看成一个子博弈 显然整个答案就是每一行的SG值的异或和 不懂的回去学SG函数... 考虑怎么分析一行的状 ...

  9. #333 Div2 Problem B Approximating a Constant Range(尺取法)

    题目:http://codeforces.com/contest/602/problem/B 题意 :给出一个含有 n 个数的区间,要求找出一个最大的连续子区间使得这个子区间的最大值和最小值的差值不超 ...

  10. hdu-4513吉哥系列故事——完美队形II--最长回文

    吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)To ...