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 ...
随机推荐
- c++语言的学习笔记代码与笔记注释《面向对象部分》
#include <iostream> /*这是C++中关于面向对象部分的具体笔记和代码 */ //定义类的语法形式; //类中的成员项目之间相互引用,直接使用成员; //类外引用成员的时 ...
- Java基础之身份证验证
//简约版package test; import java.util.Scanner; public class ID { /** * 匹配算法 : 1) 得到17位身份证号码与下面给出的17位 2 ...
- 从100PV到1亿级PV网站架构演变(转)
http://www.linuxde.net/2013/05/13581.html 一个网站就像一个人,存在一个从小到大的过程.养一个网站和养一个人一样,不同时期需要不同的方法,不同的方法下有共同的原 ...
- CF1093E Intersection of Permutations 树状数组套权值线段树
\(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...
- 牛客国庆集训day6 B Board (模拟标记思维或找规律或分块???)
链接:https://www.nowcoder.com/acm/contest/206/B来源:牛客网 题目描述 恬恬有一个nx n的数组.她在用这个数组玩游戏: 开始时,数组中每一个元素都是0. 恬 ...
- vue.js组件之j间的通讯二
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- springloud系列搭建注册中心
首先搭建父工程: 点击next父工程就搭建完成; pom.xml文件: <?xml version="1.0" encoding="UTF-8"?> ...
- elasticsearch 相关命令
ubuntu server 启动命令:$ ./bin/elasticsearch 后台运行:$ ./bin/elasticsearch -d 查看当前进程:$ jps 启动后检查是否成功命令:$ cu ...
- hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
题目传送门 题目大意: 给出一张n*n的图,机器人在一秒钟内任一格子上都可以有五种操作,上下左右或者停顿,(不能出边界,不能碰到障碍物).题目给出k个障碍物,但保证没有障碍物的地方是强联通的,问经过无 ...
- Mysql5.7.20源码编译安装
一.下载源码包 1.1 下载mysql源码包 MySQL源码,网址为:https://dev.mysql.com/downloads/mysql/ : 1.2 下载boost 下载网址为:http:/ ...