题意:有一棵树,每条边有一个距离,求dis(u,v)<=k的点的对数

题解:树分治,对于一颗树上的两点,要么在同一颗子树上,要么在不同子树上,要么一个点是根,另一个在某一子树上,对于第一种情况我们可以通过递归来变成第二种或者第三种情况。我们对于某一颗子树来说我们先统计dis[u]+dis[v]<=k的点的对数,然后把该子树的所有子节点为根的这颗子树中dis[u]+dis[v]<=k的点的对数删去,因为在递归到后面会计算重复(这是第一种情况),所以这样就得到了该子树的满足条件的点对数,那么剩下就是如何分了,要想使分的次数最小,那么我们可以每次选取该子树的重心来作为根节点,然后,每次计算完之后删除根节点,再计算所有子树,计算重心还是通过树形dp来求解,

对于树分治来说,分为点分治和边分治,点分治就是每次找到重心,然后把重心删除掉,对分成的树之间统计路径信息,直到只剩一个点的情况

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1 using namespace std;
using namespace __gnu_cxx; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f; struct edge{
int to,Next,c;
}e[maxn];
int cnt,head[N];
int sz[N],zx[N],dis[N];
int n,k;
bool vis[N];
void add(int u,int v,int c)
{
e[cnt].to=v;
e[cnt].c=c;
e[cnt].Next=head[u];
head[u]=cnt++;
}
void init()
{
cnt=;
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
}
void dfssz(int u,int f,int &sum)
{
sum++;
sz[u]=;
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dfssz(x,u,sum);
sz[u]+=sz[x];
}
}
void dfszx(int u,int f,int sum,int &ans,int &id)
{
zx[u]=sum-sz[u];
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dfszx(x,u,sum,ans,id);
zx[u]=max(zx[u],sz[x]);
}
if(ans>zx[u])
{
ans=zx[u];
id=u;
}
}
int findzx(int root)//找子树的重心
{
int sum=;
dfssz(root,-,sum);
int ans=inf,id=;
dfszx(root,-,sum,ans,id);
return id;
}
void dfsdis(int u,int f,vector<int> &son)
{
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dis[x]=dis[u]+e[i].c;
dfsdis(x,u,son);
}
son.pb(dis[u]);
}
bool comp(int a,int b)
{
return dis[a]<dis[b];
}
int ok(vector<int> &son)
{
sort(son.begin(),son.end());
// for(int i=0;i<son.size();i++)
// cout<<son[i]<<endl;
// cout<<endl;
int ans=;
for(int i=;i<son.size();i++)
{
int p=upper_bound(son.begin(),son.end(),k-son[i])-son.begin();
if(p>)p--;
if(p<=i)continue;
// cout<<p<<endl;
ans+=p-i;
}
// cout<<ans<<"*****"<<endl;
return ans;
}
void dfsson(int u,int f,vector<int> &son)
{
son.pb(dis[u]);
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dfsson(x,u,son);
}
}
int solve(int root)
{
int p=findzx(root);//找该子树的重心
memset(dis,-,sizeof dis);
dis[p]=;
vector<int>son;
son.clear();
dfsdis(p,-,son);//求子树中各点到重心的距离
int ans=ok(son);//满足该子树的dis[x]+dis[y]<=k对数;
// if(root==3)cout<<ans<<" ----"<<endl;
for(int i=head[p];~i;i=e[i].Next)
{
int x=e[i].to;
if(vis[x])continue;
son.clear();
dfsson(x,p,son);
ans-=ok(son);
}
// if(root==3)cout<<ans<<" ****"<<endl;
vis[p]=;
for(int i=head[p];~i;i=e[i].Next)
{
int x=e[i].to;
if(vis[x])continue;
ans+=solve(e[i].to);
//if(x==3)cout<<solve(e[i].to)<<"......."<<endl;
}
// if(root==3)cout<<p<<" "<<ans<<"+++++++++"<<endl;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
while(~scanf("%d%d",&n,&k))
{
if(!n&&!k)break;
init();
for(int i=;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
printf("%d\n",solve());
}
return ;
}
/*******************
4 3
1 2 3
1 3 1
1 4 2
********************/

最新文章

  1. Javascript面向对象(封装、继承)
  2. POJ 3683 Priest John&#39;s Busiest Day (2-SAT)
  3. android开发--Application
  4. ORA-01653:表空间扩展失败的问题以及增加表空间
  5. align=absMiddle属性设置
  6. c++ 完成端口资料
  7. 15_CXF和Spring开发手机号查询网站
  8. 【原】SparkContex源码解读(一)
  9. jQuery 文本框得失焦点应用
  10. jmake 编译当前目录所有c/c++单文件
  11. 201521123029《Java程序设计》第十一周学习总结
  12. insert时报Cannot add or update a child row: a foreign key constraint fails (`yanchangzichan`.`productstatusrecord`, CONSTRAINT `p_cu` FOREIGN KEY (`cid`) REFERENCES `customer` (`cid`))错误
  13. RazorEngine
  14. 【NOIP2015普及组】推销员_详解
  15. asp.net 访问页面访问统计实现
  16. oracle用exp导出dmp文件时发现空表没有导出来
  17. Windows Phone开发手记-WinRT下自定义圆形ItemsControl
  18. Spring MVC 3.0 深入及对注解的详细讲解[转载]
  19. 20155302 2016-2017-2 《Java程序设计》第七周学习总结
  20. MUI上传文件的方法

热门文章

  1. 解决httpclient抛出URISyntaxException异常
  2. Scilab 的画图函数(2)
  3. Centos6.3下Ganglia3.6.0安装配置
  4. 【深度学习】使用opencv在视频上添加文字和标记框
  5. 剑指offer 面试21题
  6. C# XMLHttpRequest对象—Ajax实例
  7. libhdfs的配置和使用
  8. Linux挂载Windows共享目录
  9. nodejs异步调用async
  10. R语言的输出函数cat,sink,writeLines,write.table