POJ 1741Tree(树分治)

本文详细介绍了树分治算法的应用场景及其实现细节,通过解决树形结构中的距离问题,展示了如何利用树的特性来划分并简化问题,最终高效地计算出所有符合条件的点对数量。
Tree
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 15035 Accepted: 4902

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001). 
Define dist(u,v)=The min distance between node u and v. 
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. 
Write a program that will count how many pairs which are valid for a given tree. 

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l. 
The last test case is followed by two zeros. 

Output

For each test case output the answer on a single line.

Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0

Sample Output

8



解题思路:

   树分治:就是将一棵树以重心分成若干个树。然后分2种情况,一种是包括根,另一种是不包括根。 对于不包括的就可以进行分治。而对于包括的就先统计每个点(当前树的点)到root的距离,利用单调性,求出两两可以配对的,不过如果两个点在同一棵子树上时就要减掉,因为在接下去的分治中,它会被统计,所以为了避免统计,要减掉。对于不要的点对可以分别统计每棵子树包括的对数。


  #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,opp;
long long sum=0;
int len=0;
struct data
 {
  int from,to,zhi,next;
 }e[91009];
int h[11001]; 
int son[11001];
bool vis[11001];
int ma,root,ge;
int lg[11001];


void insert(int x,int y,int length){++len; e[len].from=x; e[len].to=y; e[len].zhi=length; e[len].next=h[x]; h[x]=len;}


int getroot(int o,int fa)
 {
  son[o]=1;
  int u=h[o]; 
  while (u!=0)
  {
  if (e[u].to!=fa && vis[e[u].to])
  {
  son[o]+=getroot(e[u].to,o);
}
u=e[u].next;
 }
int zan=max(son[o]-1,opp-son[o]);
if (zan<ma){ma=zan;root=o;}
return son[o];
 }


int getdeep(int now,int leng,int fa)
 {  
    ++ge;
  lg[ge]=leng;
  int u=h[now];
  while (u!=0)
  {
  if (vis[e[u].to] && e[u].to!=fa)
  {
  getdeep(e[u].to,leng+e[u].zhi,now);
}
u=e[u].next;
 }
 }


int cal()
 {
  int t=0;
  for (int l=1,r=ge;l<r;)
  {
  if (lg[l]+lg[r]<=m) 
{
t+=r-l;++l;
 }else
  --r;
 }
return t;
 }


int work(int ro)
 {
  vis[ro]=false; ge=0;
  getdeep(ro,0,0); 
  sort(lg+1,lg+ge+1);
  sum+=cal();
    int u=h[ro];
    while (u!=0)
     {
      if (vis[e[u].to])
      {
      ge=0; getdeep(e[u].to,e[u].zhi,0); 
      sort(lg+1,lg+ge+1);
      sum-=cal();
      ma=0x7fffffff;
      opp=son[e[u].to];
      getroot(e[u].to,ro); work(root);
 }
u=e[u].next;
}
 }


int main()
{
while (scanf("%d %d",&n,&m) && n!=0 )
{
memset(h,0,sizeof(h)); len=0;
for (int i=1;i<=n-1;++i)
{
int x,y,length;
scanf("%d %d %d",&x,&y,&length);
insert(x,y,length); insert(y,x,length);
 }
sum=0; ma=0x7fffffff; root=0; opp=n;
memset(vis,true,sizeof(vis));
getroot(1,0);
work(root);
cout<<sum<<endl;
}
}

内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;最后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值