树形结构升级版
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 ai, bi 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 ≤ n, ui ≠ 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
5
1 2
1 3
2 4
2 5
2
1 4
3 5
2 1 1 1
5
3 4
4 5
1 4
2 4
3
2 3
1 3
3 5
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.
InputThe 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.
OutputPrint 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.
Examples11
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
2
4
0 0 0 0
1 2
2 3
3 4
0
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.