Poj_1741_Tree

Description

给一个有n个顶点的树,每个边都有一个长度(正整数小于1001)。
定义dist(u,v)=节点u和v之间的最小距离。
给出一个整数k,当且仅当dist(u,v)不超过k时,每个对(u,v)的顶点都被称为有效。
编写一个程序,计算对给定树有效的对数。

 

Input

输入包含几个测试用例。 每个测试用例的第一行包含两个整数n,k。 (n <= 10000)以下n-1行各包含三个整数u,v,l,这意味着在节点u和v之间存在长度为l的边。
最后一个测试用例后跟两个零。

 

Output

对于每个测试用例,在单行上输出答案。

 

Solution

裸的点分。

细节:注意不能同一个子树的对数不能算。

 
代码
  1 type
  2   arr=record
  3     y,w,next:longint;
  4   end;
  5 var
  6   n,s,e,nm,dt,ans,min:longint;
  7   a:array [0..200001] of arr;
  8   ls,size,v,d,deep:array [0..100001] of longint;
  9 procedure add(x,y,z:longint);
 10 begin
 11   inc(nm);
 12   a[nm].y:=y; a[nm].w:=z;
 13   a[nm].next:=ls[x]; ls[x]:=nm;
 14 end;
 15 
 16 procedure init;
 17 var
 18   i,x,y,z:longint;
 19 begin
 20   nm:=0;
 21   for i:=1 to n-1 do
 22     begin
 23       readln(x,y,z);
 24       add(x,y,z); add(y,x,z);
 25     end;
 26   ans:=0;
 27 end;
 28 
 29 procedure dfs1(x,last:longint);
 30 var
 31   i:longint;
 32 begin
 33   size[x]:=1; i:=ls[x];
 34   while i<>0 do
 35     begin
 36       if (v[a[i].y]=1) or (a[i].y=last) then
 37         begin
 38           i:=a[i].next;
 39           continue;
 40         end;
 41       dfs1(a[i].y,x);
 42       size[x]:=size[x]+size[a[i].y];
 43       i:=a[i].next;
 44     end;
 45 end;
 46 
 47 function dfs2(x,last,tot:longint):longint;
 48 var
 49   i:longint;
 50 begin
 51   i:=ls[x];
 52   while i<>0 do
 53     begin
 54       if (v[a[i].y]=1) or (a[i].y=last) or (size[a[i].y]*2<tot) then
 55         begin
 56           i:=a[i].next;
 57           continue;
 58         end;
 59       exit(dfs2(a[i].y,x,tot));
 60       i:=a[i].next;
 61     end;
 62   exit(x);
 63 end;
 64 
 65 procedure gd(x,last:longint);
 66 var
 67   i:longint;
 68 begin
 69   inc(dt); d[dt]:=deep[x];
 70   i:=ls[x];
 71   while i<>0 do
 72     begin
 73       if (a[i].y=last) or (v[a[i].y]=1) then
 74         begin
 75           i:=a[i].next;
 76           continue;
 77         end;
 78       deep[a[i].y]:=deep[x]+a[i].w;
 79       gd(a[i].y,x);
 80       i:=a[i].next;
 81     end;
 82 end;
 83 
 84 procedure qsort(l,r:longint);
 85 var
 86   mid,i,j,k:longint;
 87 begin
 88   if l>r then exit;
 89   i:=l; j:=r;
 90   mid:=d[(l+r) div 2];
 91   repeat
 92     while d[i]<mid do inc(i);
 93     while d[j]>mid do dec(j);
 94     if i<=j then
 95       begin
 96         k:=d[i]; d[i]:=d[j]; d[j]:=k;
 97         inc(i); dec(j);
 98       end;
 99   until i>j;
100   qsort(i,r);
101   qsort(l,j);
102 end;
103 
104 function js(x,cz:longint):longint;
105 var
106   i,j,num:longint;
107 begin
108   num:=0;
109   dt:=0; deep[x]:=cz;
110   gd(x,0);
111   qsort(1,dt);
112   j:=dt; i:=1;
113   while i<j do
114     if (d[i]+d[j]<=e) then
115       begin
116         num:=num+j-i;
117         inc(i);
118       end else dec(j);
119   exit(num);
120 end;
121 
122 procedure main(x:longint);
123 var
124   i:longint;
125 begin
126   ans:=ans+js(x,0);
127   v[x]:=1;
128   i:=ls[x];
129   while i<>0 do
130 
131     begin
132       if v[a[i].y]=1 then
133         begin
134           i:=a[i].next;
135           continue;
136         end;
137       ans:=ans-js(a[i].y,a[i].w);
138       dfs1(a[i].y,0);
139       main(dfs2(a[i].y,0,size[a[i].y]));
140       i:=a[i].next;
141     end;
142 end;
143 
144 begin
145   readln(n,e);
146   while (n<>0) and (e<>0) do
147     begin
148       fillchar(ls,sizeof(ls),0);
149       fillchar(v,sizeof(v),0);
150       init;
151       dfs1(1,0);
152       main(dfs2(1,0,n));
153       write(ans);
154       readln(n,e);
155     end;
156 end.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,这是一个关于二叉树遍历的问题。具体来说,给定二叉树的前序遍历和中序遍历,需要求出二叉树的后序遍历。 以下是一个Java实现的例子: ```java import java.util.Scanner; class Node { char value; Node left; Node right; public Node(char value) { this.value = value; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int t = scanner.nextInt(); while (t-- > 0) { int n = scanner.nextInt(); String preOrder = scanner.next(); String inOrder = scanner.next(); Node root = buildTree(preOrder, inOrder); postOrder(root); System.out.println(); } scanner.close(); } private static Node buildTree(String preOrder, String inOrder) { if (preOrder.length() == 0) { return null; } char rootValue = preOrder.charAt(0); int rootIndex = inOrder.indexOf(rootValue); Node root = new Node(rootValue); root.left = buildTree(preOrder.substring(1, rootIndex + 1), inOrder.substring(0, rootIndex)); root.right = buildTree(preOrder.substring(rootIndex + 1), inOrder.substring(rootIndex + 1)); return root; } private static void postOrder(Node root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.print(root.value); } } ``` 这段代码首先读取输入的测试用例数量t,然后依次读取每个测试用例的节点数量n、前序遍历和中序遍历的字符串。接下来,通过递归构建二叉树,并使用后序遍历输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值