树形结构升级版

A树的直径(模板)

Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undirected. That means you have to find two nodes in the tree whose distance is maximum amongst all nodes.

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with an integer n (2 ≤ n ≤ 30000) denoting the total number of nodes in the tree. The nodes are numbered from 0 to n-1. Each of the next n-1 lines will contain three integers u v w (0 ≤ u, v < n, u ≠ v, 1 ≤ w ≤ 10000)denoting that node u and v are connected by an edge whose weight is w. You can assume that the input will form a valid tree.

Output

For each case, print the case number and the maximum distance.

Sample Input

2

4

0 1 20

1 2 30

2 3 50

5

0 2 20

2 1 10

0 3 29

0 4 50

Sample Output

Case 1: 100

Case 2: 80

 1 var
 2 t,n,m,i,j,x,y,z,e,po,l:longint;
 3 max:int64;
 4 head,next,a,dis,w:array[-100..600005]of longint;
 5 procedure add(x,y,z:longint);
 6 begin
 7  inc(e); a[e]:=y; next[e]:=head[x];head[x]:=e; w[e]:=z;
 8 end;
 9 procedure dfs(u,m:longint);
10  var i,v:longint;
11  begin
12   i:=head[u];
13   while i>0 do
14    begin
15      v:=a[i];
16      if v<>m then
17       begin
18        if dis[u]+w[i]>dis[v] then dis[v]:=dis[u]+w[i];
19 
20          if dis[v]>max then
21         begin
22           max:=dis[v];
23           po:=v;
24        end;
25         dfs(v,u);//you wrong
26        end;
27       i:=next[i];
28    end;
29  end;
30 begin
31 readln(T);
32 for l:=1 to t do
33 begin
34 fillchar(head,sizeof(head),0);
35  fillchar(next,sizeof(next),0);
36  fillchar(a,sizeof(a),255);
37  fillchar(w,sizeof(w),0);
38   fillchar(dis,sizeof(dis),0);
39   readln(n);
40   e:=0;  dis[0]:=0;max:=0; po:=0;
41   for i:=1 to n-1 do
42    begin
43      readln(x,y,z);
44      add(x,y,z);
45      add(y,x,z);
46    end;
47   dfs(0,0);
48   fillchar(dis,sizeof(dis),0);//一定要再次清0!
49   dfs(po,po);
50  writeln('Case ',l,': ',max);
51 end;
52 end

B - 树的重心(模板)

Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to arrest the mafia leaders.

Unfortunately, the structure of Chicago mafia is rather complicated. There are npersons known to be related to mafia. The police have traced their activity for some time, and know that some of them are communicating with each other. Based on the data collected, the chief of the police suggests that the mafia hierarchy can be represented as a tree. The head of the mafia, Godfather, is the root of the tree, and if some person is represented by a node in the tree, its direct subordinates are represented by the children of that node. For the purpose of conspiracy the gangsters only communicate with their direct subordinates and their direct master.

Unfortunately, though the police know gangsters’ communications, they do not know who is a master in any pair of communicating persons. Thus they only have an undirected tree of communications, and do not know who Godfather is.

Based on the idea that Godfather wants to have the most possible control over mafia, the chief of the police has made a suggestion that Godfather is such a person that after deleting it from the communications tree the size of the largest remaining connected component is as small as possible. Help the police to find all potential Godfathers and they will arrest them.

Input

The first line of the input file contains n — the number of persons suspected to belong to mafia (2 ≤ n ≤ 50 000). Let them be numbered from 1 to n.

The following n − 1 lines contain two integer numbers each. The pair aibi means that the gangster ai has communicated with the gangster bi. It is guaranteed that the gangsters’ communications form a tree.

Output

Print the numbers of all persons that are suspected to be Godfather. The numbers must be printed in the increasing order, separated by spaces.

Sample Input

6
1 2
2 3
2 5
3 4
3 6

Sample Output

2 3
题意就是让你求出所有重心啦
题解:在做完这题之后我意识到一个很不得了的事情——在循环中(或dfs)中多次使用fillchar,,,会超时!因为这个东西只是代替了for循环(可能快一点),而且它for的边界是你的数组大小
这就很容易超时了。另外在这一题中,你需要知道树重心的一个性质,一颗树最多只有两个重心,所以在求重心的时候你只需要开两个变量就行了,不需要开数组,这可能也会超时。
 1 var
 2 e,n,i,j,x,y,ans,tot,t,tot1,tot2:longint;
 3 size,head,next,son,a:array[0..300005]of longint;
 4 procedure add(x,y:longint);
 5  begin
 6   inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e;
 7  end;
 8  function max(x,y:longint):longint;
 9   begin
10     if x>y then exit(x) else exit(y);
11   end;
12 procedure  dfs(u,m:longint);
13 var v,i,k,tem:longint;
14 begin
15 tem:=0;
16  i:=head[u];
17  while i>0 do
18   begin
19    v:=a[i];
20    if v<>m then
21     begin
22       dfs(v,u);
23       son[u]:=son[u]+son[v]+1;
24       tem:=max(tem,son[v]+1);
25     end;
26    i:=next[i];
27   end;
28   k:=max(tem,n-son[u]-1);
29   if k<ans then
30     begin
31      tot2:=0;
32      tot1:=u;
33      ans:=k;
34     end
35      else
36      if k=ans then
37       begin
38         tot2:=u;
39       end;
40 end;
41 begin
42  readln(n);
43  ans:=1<<30;
44  for i:=1 to n-1 do
45   begin
46    readln(x,y);
47    add(x,y);
48    add(y,x);
49   end;
50   dfs(1,1);
51   if (tot2<>0)and(tot1>tot2) then begin t:=tot1;tot1:=tot2;tot2:=t;end;
52    if tot2=0 then writeln(tot1)
53    else writeln(tot1,' ',tot2);
54 end.

C - Fools and Roads

They say that Berland has exactly two problems, fools and roads. Besides, Berland has n cities, populated by the fools and connected by the roads. All Berland roads are bidirectional. As there are many fools in Berland, between each pair of cities there is a path (or else the fools would get upset). Also, between each pair of cities there is no more than one simple path (or else the fools would get lost).

But that is not the end of Berland's special features. In this country fools sometimes visit each other and thus spoil the roads. The fools aren't very smart, so they always use only the simple paths.

A simple path is the path which goes through every Berland city not more than once.

The Berland government knows the paths which the fools use. Help the government count for each road, how many distinct fools can go on it.

Note how the fools' paths are given in the input.

Input

The first line contains a single integer n (2 ≤ n ≤ 105) — the number of cities.

Each of the next n - 1 lines contains two space-separated integers ui, vi (1 ≤ ui, vi ≤ nui ≠ vi), that means that there is a road connecting cities ui and vi.

The next line contains integer k (0 ≤ k ≤ 105) — the number of pairs of fools who visit each other.

Next k lines contain two space-separated numbers. The i-th line (i > 0) contains numbers ai, bi (1 ≤ ai, bi ≤ n). That means that the fool number 2i - 1 lives in city ai and visits the fool number 2i, who lives in city bi. The given pairs describe simple paths, because between every pair of cities there is only one simple path.

Output

Print n - 1 integer. The integers should be separated by spaces. The i-th number should equal the number of fools who can go on the i-th road. The roads are numbered starting from one in the order, in which they occur in the input.

Examples

Input
5
1 2
1 3
2 4
2 5
2
1 4
3 5
Output
2 1 1 1 
Input
5
3 4
4 5
1 4
2 4
3
2 3
1 3
3 5
Output
3 1 1 1 

Note

In the first sample the fool number one goes on the first and third road and the fool number 3 goes on the second, first and fourth ones.

In the second sample, the fools number 1, 3 and 5 go on the first road, the fool number 5 will go on the second road, on the third road goes the fool number 3, and on the fourth one goes fool number 1.

 题意:呃呃,就是说有n个城市,给你n-1条边,有m个人,需要从a[i]走到b[i]去,每走过一条边,这条边就加1,最后输出所有边被走过几次。

题解:每次加1?让我想到上次比赛的第二题——差分(其实这是我后来才想到的)。n个点,n-1条,可以知道这是棵树,以1为根节点,转为有根树,

两点之间走? 想到LCA求距离的模板,但这里不是求距离,需要改一下,走的时候给走过的边权加1?邻接表存的LCA做的时候边用不上啊,怎么办,

这时候就需要用到树上差分了,从x走到y ,dis[x]+1;dis[y]+1;  dis[LCA(x,y)]-2;这是差分的思想,最后从叶节点往上跑一直到根节点,边权就等于相邻的叶子节点

怎么实现?深搜从根节点开始,回溯的时候父亲节点+=儿子节点,然后把边权赋为相邻叶子节点的值。就完成啦!还有些小细节,详见代码

 1 var
 2 f:array[0..300005,0..24]of longint;
 3 a,dep,head,next,rd,dis,ans,map:array[0..500005]of longint;
 4 e,v,i,u,n,m,j,k,x,y,root,tot:longint;
 5 procedure add(x,y:longint);
 6 begin
 7  inc(e); a[e]:=y;next[e]:=head[x];head[x]:=e; inc(rd[y]);
 8 end;
 9 procedure dfs(u:longint);
10 var i,v:longint;
11   begin
12   i:=head[u];
13   while i>0 do
14    begin
15      v:=a[i];
16      if dep[v]=0 then
17       begin
18        dep[v]:=dep[u]+1;
19        f[v,0]:=u;
20        dfs(v);
21       end;
22       i:=next[i];
23    end;
24  end;
25  procedure rdfs(u,s:longint);
26  var v,i:longint;
27  begin
28    i:=head[u];
29    while i>0 do
30     begin
31       v:=a[i];
32       if v<>s then//不能用dep[v]>dep[u]作为条件!这样会WA,要v不等于它的爷爷节点才行(貌似我打过的关于树的都是这样写的
33        begin
34          rdfs(v,u);
35        //   writeln(u,' ',v);
36          dis[u]:=dis[u]+dis[v];
37          ans[map[i]]:=ans[map[i]]+dis[v];
38        end;
39        i:=next[i];
40     end;
41   end;
42   function lca(x,y:longint):longint;
43  var k,i:longint;
44   begin
45     if dep[x]<dep[y] then
46     begin
47       k:=x;x:=y;y:=k;
48     end;
49 
50     for i:=20 downto 0 do
51      begin
52       if dep[f[x,i]]>=dep[y] then begin x:=f[x,i];  end;
53      end;
54          if x=y then begin exit(x); end;
55      for i:=20 downto 0 do
56        if f[x,i]<>f[y,i] then
57         begin
58           x:=f[x,i];
59           y:=f[y,i];
60         end;
61    exit(f[x,0]);
62   end;
63 
64 begin
65  readln(n);
66  for i:=1 to n-1 do
67   begin
68     inc(tot);
69     readln(x,y);
70     add(x,y);
71     map[e]:=tot;//小技巧,建边两次,这样是为了最后输出每条边被走过几次
72     add(y,x);
73     map[e]:=tot;
74   end;
75   root:=1;dep[root]:=1;
76   dfs(root);
77    for i:=1 to 20 do
78     for j:=1 to n do
79      f[j,i]:=f[f[j,i-1],i-1];
80    readln(m);
81    for i:=1 to m do
82     begin
83      readln(x,y);
84      inc(dis[x]);inc(dis[y]);
85      dec(dis[lca(x,y)],2);
86     end;
87     rdfs(1,1);
88     for i:=1 to tot do write(ans[i],' ');
89 end.

E - Anton and Tree

Anton is growing a tree in his garden. In case you forgot, the tree is a connected acyclic undirected graph.

There are n vertices in the tree, each of them is painted black or white. Anton doesn't like multicolored trees, so he wants to change the tree such that all vertices have the same color (black or white).

To change the colors Anton can use only operations of one type. We denote it as paint(v), where v is some vertex of the tree. This operation changes the color of all vertices u such that all vertices on the shortest path from v to u have the same color (including v and u). For example, consider the tree

and apply operation paint(3) to get the following:

Anton is interested in the minimum number of operation he needs to perform in order to make the colors of all vertices equal.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of vertices in the tree.

The second line contains n integers colori (0 ≤ colori ≤ 1) — colors of the vertices. colori = 0 means that the i-th vertex is initially painted white, while colori = 1 means it's initially painted black.

Then follow n - 1 line, each of them contains a pair of integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — indices of vertices connected by the corresponding edge. It's guaranteed that all pairs (ui, vi) are distinct, i.e. there are no multiple edges.

Output

Print one integer — the minimum number of operations Anton has to apply in order to make all vertices of the tree black or all vertices of the tree white.

Examples
Input
11
0 0 0 1 1 0 1 0 0 1 1
1 2
1 3
2 4
2 5
5 6
5 7
3 8
3 9
3 10
9 11
Output
2
Input
4
0 0 0 0
1 2
2 3
3 4
Output
0
Note

In the first sample, the tree is the same as on the picture. If we first apply operation paint(3) and then apply paint(6), the tree will become completely black, so the answer is 2.

In the second sample, the tree is already white, so there is no need to apply any operations and the answer is 0.

题意:给你一颗树,节点被染了黑白两种颜色,但个数不确定。若一个子连通块 都为种颜色,则一次操作可以把这个连通块变为另一种颜色,现在要把树的节点

都变为一种颜色,问最少操作几次。

题解:既然一次操作能把一个连通块中节点都变色,是不是可以将他们变为一组来算更方便呢?那么第一步就是缩点了,将颜色相同的一个连通块缩为一个点,

再重新建边,得到的就是一个黑白树了(相邻节点颜色都不相同)。那操作几次怎么算?操作一次可以把一个点周围的点都变为同一种颜色,要操作的次数就是

直径/2 了,证明的话到时候再放上来。

 1 var
 2 t,n,m,i,j,x,y,z,e,ei,l,tot,po,v:longint;
 3 max:int64;
 4 c,b,head,next,a,ia,inext,ihead,xx,dis:array[-100..500005]of longint;
 5 procedure add(x,y:longint);
 6 begin
 7  inc(e); a[e]:=y; next[e]:=head[x];head[x]:=e; xx[e]:=x;
 8 end;
 9 procedure iadd(x,y:longint);
10 begin
11  inc(ei); ia[ei]:=y; inext[ei]:=ihead[x];ihead[x]:=ei;
12 end;
13 procedure dfsclo(u,m:longint);
14  var i,v:longint;
15   begin
16   i:=head[u];
17   while i>0 do
18    begin
19      v:=a[i];
20      if (c[u]=c[v])and(v<>m) then
21      begin
22        b[v]:=b[u];
23        dfsclo(v,u);
24      end;
25      i:=next[i];
26    end;
27 
28  end;
29 procedure dfs(u,m:longint);
30  var i,v:longint;
31  begin
32   i:=ihead[u];
33   while i>0 do
34    begin
35      v:=ia[i];
36      if v<>m then
37       begin
38         dis[v]:=dis[u]+1;
39         if dis[v]>max then
40          begin
41            max:=dis[v];
42            po:=v;
43          end;
44         dfs(v,u);
45        end;
46       i:=inext[i];
47    end;
48  end;
49 begin
50   readln(n);
51  for i:=1 to n do read(c[i]);
52   for i:=1 to n-1 do
53    begin
54      readln(x,y);
55      add(x,y);
56      add(y,x);
57    end;
58   for i:=1 to n do
59    begin
60     if b[i]=0 then
61      begin
62        inc(tot);
63        b[i]:=tot;
64        dfsclo(i,i);
65      end;
66    end;
67   for i:=1 to e do
68    begin
69     if  b[xx[i]]<>b[a[i]] then
70      begin
71       iadd(b[xx[i]],b[a[i]]);
72     //   iadd(b[a[i]],b[xx[i]]);
73      end;
74    end;
75  //  for i:=1 to n do writeln(b[i], ' ');
76    dfs(1,1);
77    fillchar(dis,sizeof(dis),0);
78    dfs(po,po);
79    writeln((max+1) div 2);
80 end.
NOIP2018 rp++
原文地址:https://www.cnblogs.com/brilliant107/p/9413641.html