poj 1741 两点距离小于K(树DP)
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)的更多相关文章
- poj 1987 节点距离小于等于K(树DP)
这题和poj 1741是一模一样的 但是1741能AC的代码,在这里却是TLE,暂时没看出哪里出现了问题.. AC代码: #include <iostream> #include < ...
- Life Forms POJ - 3294(不小于k个字符串中的最长子串)
题意: 求不小于字符串一半长度个字符串中的最长字串 解析: 论文题例11 将n个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开, 求后缀数组, 然后二分答案变为判定性问题, 然后判断每组的 ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- [51NOD1405] 树的距离之和(树DP)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405 (1)我们给树规定一个根.假设所有节点编号是0-(n-1 ...
- POJ 1741 Tree 树形DP(分治)
链接:id=1741">http://poj.org/problem?id=1741 题意:给出一棵树,节点数为N(N<=10000),给出N-1条边的两点和权值,给出数值k,问 ...
- POJ - 1741 Tree
DescriptionGive a tree with n vertices,each edge has a length(positive integer less than 1001).Defin ...
- POJ 1741 Tree 求树上路径小于k的点对个数)
POJ 174 ...
- 树的点分治 (poj 1741, 1655(树形dp))
poj 1655:http://poj.org/problem?id=1655 题意: 给无根树, 找出以一节点为根, 使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
随机推荐
- 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化)
传送门 我可能根本就没有学过斜率优化…… 我们设$dis[i]$表示第$i$棵树到山脚的距离,$sum[i]$表示$w$的前缀和,$tot$表示所有树运到山脚所需要的花费,$dp[i]$表示将第二个锯 ...
- Apache虚拟主机-解惑篇
有很多平时喜欢钻研的童鞋会发现,为什么有时候自己访问某XXse网站时,总是更新IP地址,内容却与以前一样.这个时候就要了解虚拟主机的概念了.了解这个概念,能够帮助运维同学,更内涵的隐藏自己的主 ...
- 转载《centos6安装nginx最详细步骤》
出处:https://www.cnblogs.com/hltswd/p/6956264.html 第一步:在centos下面下载 nginx wget http://nginx.or ...
- 传球游戏 dp
题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:nnn个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每 ...
- linux 虚拟环境问题
1.python环境 python2和python3命令用来区分python版本 pip2和pip3命令用来区分pip,你的包到底安装在哪里pip3 install xxx sudo apt inst ...
- Python利用百度地图api批量获取地址经纬度
1.pip安装xlrd,xlwt,requests模块. 2.在工程目录处放置地点Excel文件. python2.7.13代码: #coding:utf-8 import xlrd import x ...
- STS(spring tool suite)修改默认编码
安装STS后首先要做的修改默认编码: 1.windows--perferences--general--workspace,Text file encoding设置成utf-8 2.windows-- ...
- maven 中 指定jdk 和 编译编码,仓库位置
<!-- 配置编译选项 --> <profile> <id>jdk1.8</id> <activation> <activeByDef ...
- Canvas制作动态进度加载水球
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 51Nod - 1242 斐波那契(快速幂)
斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, ...