C. Andryusha and Colored Balloons
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Andryusha goes through a park each day. The squares and paths between them look boring to Andryusha, so he decided to decorate them.
The park consists of n squares connected with (n - 1) bidirectional paths in such a way that any square is reachable from any other using these paths. Andryusha decided to hang a colored balloon at each of the squares. The baloons' colors are described by positive integers, starting from 1. In order to make the park varicolored, Andryusha wants to choose the colors in a special way. More precisely, he wants to use such colors that if a, b and c are distinct squares that a and b have a direct path between them, and b and c have a direct path between them, then balloon colors on these three squares are distinct.
Andryusha wants to use as little different colors as possible. Help him to choose the colors!
Input
The first line contains single integer n (3 ≤ n ≤ 2·105) — the number of squares in the park.
Each of the next (n - 1) lines contains two integers x and y (1 ≤ x, y ≤ n) — the indices of two squares directly connected by a path.
It is guaranteed that any square is reachable from any other using the paths.
Output
In the first line print single integer k — the minimum number of colors Andryusha has to use.
In the second line print n integers, the i-th of them should be equal to the balloon color on the i-th square. Each of these numbers should be within range from 1 to k.
Examples
input
Copy
3
2 3
1 3
output
Copy
3
1 3 2
input
Copy
5
2 3
5 3
4 3
1 3
output
Copy
5
1 3 2 5 4
input
Copy
5
2 1
3 2
4 3
5 4
output
Copy
3
1 2 3 1 2
Note
In the first sample the park consists of three squares: 1 → 3 → 2. Thus, the balloon colors have to be distinct.
Illustration for the first sample.
In the second example there are following triples of consequently connected squares:
- 1 → 3 → 2
- 1 → 3 → 4
- 1 → 3 → 5
- 2 → 3 → 4
- 2 → 3 → 5
- 4 → 3 → 5
We can see that each pair of squares is encountered in some triple, so all colors have to be distinct.
Illustration for the second sample.
In the third example there are following triples:
- 1 → 2 → 3
- 2 → 3 → 4
- 3 → 4 → 5
We can see that one or two colors is not enough, but there is an answer that uses three colors only.
Illustration for the third sample
题意:给你一棵树,距离为1或2的节点颜色不能相同,求最小颜色数方案。
题解:bfs搜点,记录父亲和爷爷节点,儿子与他们的颜色不能相同,那bfs如何写?因为我们采用的是邻接表,所以每次将该节点的所有出边全部遍历一遍,然后再对于下一个点dfs,
因为是树,所以每个节点只会被遍历一遍,不需要用队列优化。
1 var 2 head,next,a,dep,col:array[0..400000]of longint; 3 i,e,x,y,n,ans:longint; 4 5 procedure add(x,y:longint); 6 begin 7 inc(e); a[e]:=y; next[e]:=head[x];head[x]:=e; 8 end; 9 procedure dfs(u,m:longint); 10 var j,l,v,i,k:longint; 11 begin 12 k:=1; 13 i:=head[u]; 14 while i>0 do 15 begin 16 v:=a[i]; 17 if v<>m then 18 begin 19 while (col[u]=k)or(col[m]=k) do inc(k);//此处 20 col[v]:=k; 21 inc(k); 22 end; 23 i:=next[i]; 24 end; 25 j:=head[u]; 26 while j>0 do 27 begin 28 v:=a[j]; 29 if v<>m then dfs(v,u); 30 j:=next[j]; 31 end; 32 33 end; 34 begin 35 readln(n); 36 for i:=1 to n-1 do 37 begin 38 readln(x,y); 39 add(x,y); 40 add(y,x); 41 end; 42 col[1]:=1; 43 dfs(1,0); 44 45 for i:=1 to n do if ans<col[i] then ans:=col[i]; 46 writeln(ans); 47 //for i:=1 to n do writeln(dep[i]); 48 for i:=1 to n do write(col[i],' '); 49 end.
Alyona decided to go on a diet and went to the forest to get some apples. There she unexpectedly found a magic rooted tree with root in the vertex 1, every vertex and every edge of which has a number written on.
The girl noticed that some of the tree's vertices are sad, so she decided to play with them. Let's call vertex v sad if there is a vertex u in subtree of vertex vsuch that dist(v, u) > au, where au is the number written on vertex u, dist(v, u) is the sum of the numbers written on the edges on the path from v to u.
Leaves of a tree are vertices connected to a single vertex by a single edge, but the root of a tree is a leaf if and only if the tree consists of a single vertex — root.
Thus Alyona decided to remove some of tree leaves until there will be no any sad vertex left in the tree. What is the minimum number of leaves Alyona needs to remove?
InputIn the first line of the input integer n (1 ≤ n ≤ 105) is given — the number of vertices in the tree.
In the second line the sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 109) is given, where ai is the number written on vertex i.
The next n - 1 lines describe tree edges: ith of them consists of two integers pi and ci (1 ≤ pi ≤ n, - 109 ≤ ci ≤ 109), meaning that there is an edge connecting vertices i + 1 and pi with number ci written on it.
OutputPrint the only integer — the minimum number of leaves Alyona needs to remove such that there will be no any sad vertex left in the tree.
Example9
88 22 83 14 95 91 98 53 11
3 24
7 -8
1 67
1 64
9 65
5 12
6 -80
3 8
5
题意:如果在v的子树中存在结点u 使得dis(v, u) > node[u],那么结点v就是sad结点,dis(v, u)代表从结点v出发到结点u的权值和,sad点要删除,问至少删几个点
题解:刚开始其实想的太简单了,现在来更正一下思路,从树根dfs下去,记录边权和,这里要注意,因为是对于每一个子树都要有题意的那种情况,所以在记录边权和的时候,
负数的话(这条边是肯定行的,节点值>1)所以记dis的时候,应该这样max{dis[u]+w[i],w[i]},dis[u]可能为负,那就取正的w[i],因为下一个子树需要下一条边权,
如果大于子树根节点,则子树被删,如果直接dis值拿来加的话,这时候到此子树dis值就可能为负了,该子树就取了,而这就错了。
1 var 2 n,i,j,z,x,e,ans:longint; 3 bj:array[0..400005]of 0..1; 4 a,head,next,w,b,rd,dis:array[0..400005]of longint; 5 function max(x,y:longint):longint; 6 begin 7 if x>y then exit(x) else exit(y); 8 end; 9 procedure add(x,y,z:longint); 10 begin 11 inc(e); b[e]:=y;next[e]:=head[x];head[x]:=e;w[e]:=z; inc(rd[y]); 12 end; 13 procedure dfs(u,last:longint); 14 var i,v:longint; 15 begin 16 if dis[u]>a[u] then exit; 17 bj[u]:=1; 18 i:=head[u]; 19 while i>0 do 20 begin 21 v:=b[i]; 22 if v<>last then 23 begin 24 dis[v]:=max(dis[u]+w[i],w[i]); 25 dfs(v,u); 26 end; 27 i:=next[i]; 28 end; 29 end; 30 begin 31 readln(n); 32 for i:=1 to n do 33 read(a[i]); 34 for i:=2 to n do 35 begin 36 readln(x,z); 37 add(x,i,z); 38 add(i,x,z); 39 end; 40 dfs(1,1); 41 for i:=1 to n do if bj[i]=0 then inc(ans); 42 writeln(ans); 43 end.
After the piece of a devilish mirror hit the Kay's eye, he is no longer interested in the beauty of the roses. Now he likes to watch snowflakes.
Once upon a time, he found a huge snowflake that has a form of the tree (connected acyclic graph) consisting of n nodes. The root of tree has index 1. Kay is very interested in the structure of this tree.
After doing some research he formed q queries he is interested in. The i-th query asks to find a centroid of the subtree of the node vi. Your goal is to answer all queries.
Subtree of a node is a part of tree consisting of this node and all it's descendants (direct or not). In other words, subtree of node v is formed by nodes u, such that node v is present on the path from u to root.
Centroid of a tree (or a subtree) is a node, such that if we erase it from the tree, the maximum size of the connected component will be at least two times smaller than the size of the initial tree (or a subtree).
Input
The first line of the input contains two integers n and q (2 ≤ n ≤ 300 000, 1 ≤ q ≤ 300 000) — the size of the initial tree and the number of queries respectively.
The second line contains n - 1 integer p2, p3, ..., pn (1 ≤ pi ≤ n) — the indices of the parents of the nodes from 2 to n. Node 1 is a root of the tree. It's guaranteed that pi define a correct tree.
Each of the following q lines contain a single integer vi (1 ≤ vi ≤ n) — the index of the node, that define the subtree, for which we want to find a centroid.
Output
For each query print the index of a centroid of the corresponding subtree. If there are many suitable nodes, print any of them. It's guaranteed, that each subtree has at least one centroid.
Example
7 4
1 1 3 3 5 3
1
2
3
5
3
2
3
6
题意:需要找到每颗子树的重心,有q个询问,询问每颗子树的重心。
题解:先敲一个重心模板,再在回溯的时候,对于每个节点,如果它的儿子节点拥有的儿子节点的两倍大于它的拥有的儿子节点,则该节点重心一定在该节点的儿子节点下,
咳咳。。还是详见代码吧,这里讲不清。
1 var 2 tmp,v,i,n,k,q,e,size,x,y,m:longint; 3 vis:array[0..300005]of boolean; 4 ans,fa,son,head,a,next:array[0..300005]of longint; 5 function max(x,y:longint):longint; 6 begin 7 if x>y then exit(x) else exit(y); 8 end; 9 procedure add(x,y:longint); 10 begin 11 inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e; 12 end; 13 procedure dfs(u:longint); 14 var l,i,v,j:longint; 15 begin 16 //vis[u]:=true; 17 ans[u]:=u; 18 son[u]:=1; 19 i:=head[u]; 20 while i>0 do 21 begin 22 v:=a[i]; 23 // if not vis[v] then 24 // begin 25 dfs(v); 26 son[u]:=son[u]+son[v]+1; 27 // end; 28 i:=next[i]; 29 end; 30 j:=head[u]; 31 // if u=2 then writeln(ans[u]); 32 while j>0 do 33 begin 34 v:=a[j]; 35 if (son[v]*2>son[u])and(v<>fa[u]) then ans[u]:=ans[v];//更新重心,在v子树中 36 37 while (son[u]-son[ans[u]])*2>son[u] do //这时候重心不一定最优,如果u和v的重心之间的节点数量*2大于u的儿子数量,则u的重心需要往上移,直到不符合 多半优势 38 begin 39 ans[u]:=fa[ans[u]]; 40 end; 41 j:=next[j]; 42 end; 43 end; 44 begin 45 readln(n,m); 46 for i:=2 to n do 47 begin 48 read(x); 49 fa[i]:=x; 50 add(fa[i],i); 51 // add(x,i); 52 end; 53 dfs(1); 54 // for i:=1 to n-1 do writeln(ans[i]); 55 for i:=1 to m do 56 begin 57 readln(x); 58 writeln(ans[x]); 59 end; 60 end.
Alice got tired of playing the tag game by the usual rules so she offered Bob a little modification to it. Now the game should be played on an undirected rooted tree of n vertices. Vertex 1 is the root of the tree.
Alice starts at vertex 1 and Bob starts at vertex x (x ≠ 1). The moves are made in turns, Bob goes first. In one move one can either stay at the current vertex or travel to the neighbouring one.
The game ends when Alice goes to the same vertex where Bob is standing. Alice wants to minimize the total number of moves and Bob wants to maximize it.
You should write a program which will determine how many moves will the game last.
Input
The first line contains two integer numbers n and x (2 ≤ n ≤ 2·105, 2 ≤ x ≤ n).
Each of the next n - 1 lines contains two integer numbers a and b (1 ≤ a, b ≤ n) — edges of the tree. It is guaranteed that the edges form a valid tree.
Output
Print the total number of moves Alice and Bob will make.
Examples
4 3
1 2
2 3
2 4
4
5 2
1 2
2 3
3 4
2 5
6
题意:A和B在玩一个游戏,就是B追A了,A先出发,A希望游戏持续时间长,B希望游戏持续时间短 ,求游戏持续时间
题解:A和B每次移动距离一样,则只要A有路可走,B就追不上A,最终AB一定在叶子节点,这样距离才最长,符合A的希望(B的希望毫无软用)游戏时间唯一。只要dfs出根节点到每个叶子节点的距离,还有B所在节点到所有叶子节点距离
然后取差值最大的就是答案。
var x,y,e,n,s,i:longint; ans:int64; head,a,rd,next,d1,d2:array[0..400005]of longint; procedure add(x,y:longint); begin inc(e); next[e]:=head[x];head[x]:=e;a[e]:=y; inc(rd[y]); end; procedure dfs(u,last,step:longint); var i,v:longint; begin i:=head[u]; if (rd[u]=1)and(u<>1) then begin d1[u]:=step; end; while i>0 do begin v:=a[i]; if (v<>last) then begin dfs(v,u,step+1); end; i:=next[i]; end; end; procedure dfs2(u,last,step:longint); var i,v:longint; begin i:=head[u]; if (rd[u]=1)and(u<>1) then begin d2[u]:=step; end; while i>0 do begin v:=a[i]; if (v<>last) then begin dfs2(v,u,step+1); end; i:=next[i]; end; end; begin readln(n,s); for i:=1 to n-1 do begin readln(x,y); add(x,y); add(y,x); end; dfs(1,1,0); dfs2(s,s,0); for i:=2 to n do begin if rd[i]=1 then if d1[i]>d2[i] then if ans<d1[i]*2 then ans:=d1[i]*2; end; writeln(ans); end.
codeforces 980E The Number Games
题目大意:
题目大意 : 有一棵点数为 n 的数,第 ii 个点的点权是 2i 你需要删掉 k 个点,使得删掉这些点后树依然联通,且剩下的点权之和最大,并输出方案
n,k≤1000000
解题思路 :
该问题可以转化为选取 n−k个点,使得选取的点联通且权值和最大
根据点权是 2i,有选取编号为 x 的点比选取 i=[1,x)之间的所有点还要优(手推一下就知道啦)
首先 n 一定要保留,于是可以将 n设置为 root 把无根树变成有根树来简化问题
接下来不妨贪心的从大到小枚举点,对于当前的点,判断是否已经被标记,如果没有被标记,那么就找到离当前点最远的没有被标记的祖先,
如果要标记这个点,那么总共增加的点就是从当前点到离当前点最远的没有被标记的祖先的路径上的所有点的数量,也可以解释为当前点到已经保留的点所构成的树的路径上的点。
所以对于一个点 x 只需要倍增找到其到 root 路径上最深的未被选取的点 y
那么路径上没有被选取的点的个数就是 dep[x]-dep[y]+1如果可以选取就dfs枚举这些点并标记为取。
因为每个点只会被最多选取一次,总复杂度是 O(nlogn)
1 var 2 a,next,head,dep:array[0..2000005]of longint; 3 f:array[0..1000005,0..24]of longint; 4 vis:array[0..2000005]of boolean; 5 i,n,m,k,e,root,u,v,fi,j,x,y:longint; 6 procedure add(x,y:longint); 7 begin 8 inc(e);a[e]:=y;next[e]:=head[x];head[x]:=e; 9 end; 10 procedure dfs(x:longint);//预处理深度 11 var i,v:longint; 12 begin 13 i:=head[x]; 14 while i>0 do 15 begin 16 v:=a[i]; 17 if dep[v]=0 then 18 begin 19 dep[v]:=dep[x]+1; 20 f[v,0]:=x; 21 dfs(v); 22 end; 23 i:=next[i]; 24 end; 25 end; 26 function get(x:longint):longint;//找最远的未被访问的点,倍增 27 var i:longint; 28 begin 29 for i:=22 downto 0 do 30 begin 31 if (not(vis[f[x,i]]))and(f[x,i]<>0)then x:=f[x,i]; 32 end; 33 exit(x); 34 end; 35 procedure redfs(u,x:longint);//向上标记点 36 var i:longint; 37 begin 38 vis[u]:=true; 39 if u=x then exit; 40 redfs(f[u,0],x); 41 end; 42 begin 43 readln(n,k);k:=n-k-1;//节点n占掉一个位子 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 root:=n; 51 f[root,0]:=root;//预处理 52 dep[root]:=1; 53 dfs(root); 54 55 for i:=1 to 22 do 56 for j:=1 to n do 57 begin 58 f[j,i]:=f[f[j,i-1],i-1];//倍增初始化 59 end; 60 vis[n]:=true; 61 for i:=n-1 downto 1 do 62 if not vis[i] then 63 begin 64 u:=i;fi:=get(u); 65 if dep[u]-dep[fi]+1<=k then 66 begin 67 k:=k-(dep[u]-dep[fi]+1); 68 // writeln(k); 69 redfs(u,fi); 70 end; 71 end; 72 for i:=1 to n do if not vis[i] then write(i,' '); 73 end.