zoukankan      html  css  js  c++  java
  • 树形结构升级版

    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++
  • 相关阅读:
    vue简单分屏(1,4,9,16),全屏,还需要调整
    vue 中的Vuex实践
    常用工具类
    java Log日志规范
    spring中对象的注入方式
    不恰当的update语句使用主键和索引导致mysql死锁
    JPA规范及其它持久层框架
    webservice基本功能介绍
    Activiti工作流(二)之常用操作
    Activiti工作流(一)之基本操作介绍
  • 原文地址:https://www.cnblogs.com/brilliant107/p/9413641.html
Copyright © 2011-2022 走看看