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. ubuntu部署django详细教程

    教程使用的软件版本:Ubuntu 18.04.1 LTS,django2.0,Python 3.6.5.nginx-1.13.7.uWSGI (2.0.17.1),Ubuntu是纯净的,全新的.下面我 ...

  2. JAVA 正则表达式的三种模式: 贪婪, 勉强和占有的讨论

    假设待处理的字符串是  xfooxxxxxxfoo 模式.*foo (贪婪模式): 模式分为子模式p1(.*)和子模式p2(foo)两个部分. 其中p1中的量词匹配方式使用默认方式(贪婪型). 匹配开 ...

  3. 5分钟构建无服务器敏感词过滤后端系统(基于FunctionGraph)

    摘要:开发者通过函数工作流,无需配置和管理服务器,以无服务器的方式构建应用,便能开发出一个弹性高可用的后端系统.托管函数具备以毫秒级弹性伸缩.免运维.高可靠的方式运行,极大地提高了开发和运维效率,减小 ...

  4. springboot整合fastdfs

    首先pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

  5. Codeforces Round #532 (Div. 2)- A(思维)

    This morning, Roman woke up and opened the browser with nn opened tabs numbered from 11 to nn. There ...

  6. ymPrompt.js消息提示组件

    转载:https://www.cnblogs.com/linzheng/archive/2010/11/15/1878058.html 使用说明: 1.在页面中引入ymPrompt.js.如:< ...

  7. Zookeeper查看版本

    [root@ooccpp lib]# Zookeeper version: ---, built on // : GMT Clients: /[](queued=,recved=,sent=) /[] ...

  8. 在Docker中部署Asp.net core2.1以及修改发布

    https://blog.csdn.net/sd7o95o/article/details/80809734   本篇文章主要是如何在Docker容器中运行ASP.NET Core应用程序,以及修改系 ...

  9. python_爬虫基础学习

    ——王宇阳—根据mooc课程总结记录笔记(Code_boy) Requests库:自动爬去HTML页面.自动网络请求提交 robots.txt:网络爬虫排除标准 Beautiful Soup库:解析H ...

  10. equals和等号的区别

    如果是基本类型,等号比较的是数值.如果是引用类型,等号比较的是地址.而equals如果没有重写的话默认比较的是地址,可以重写equals来自定义比较两个对象的逻辑.