關於樹形結構的一點東西

前言: 考試樹形結構太頻繁惹菜雞鈞鈞屁也不會!(霧

1.樹的直徑:

衆所周知的兩種求法:數組

  • 兩遍\(dfs\)
    信奧不須要證實
    第一遍\(dfs\)搜到樹的最深葉節點,而後把這個葉節點拎起來做爲根再\(dfs\)到最深葉節點。
    *最深指按照邊長算距離根節點最遠。
    代碼:
void dfs_R1(int x, int fa, int depth) {
    if(depth > Max) Max = depth, Rs = x;
    for(int i = head[x]; i; i = edg[i].nxt) {
      if(edg[i].v == fa) continue;
      dfs_R1(edg[i].v, x, depth + edg[i].w);
    }
  }
   void dfs_R2(int x, int fa, int depth) {
    if(depth > ans) ans = depth, Re = x;
    for(int i = head[x]; i; i = edg[i].nxt) {
      if(edg[i].v == fa) continue;
      dfs_R2(edg[i].v, x, depth + edg[i].w);
    }
  }
  • 樹形\(DP\)
    對於每一個節點,維護其子樹中的最長鏈和次長鏈,設數組f[x][1]表示最長鏈,f[x][2]表示次長鏈。更新時,若「鏈接兒子的邊\(+\)此兒子子樹中的最長鏈」大於當前最長鏈,則當前最長鏈變爲次長鏈,最長鏈變爲鏈接兒子的邊\(+\)此兒子子樹中的最長鏈,若大於次長鏈小於最長鏈則只更新次長鏈。樹的直徑必然爲某一節點子樹中的最長鏈\(+\)次長鏈。
    代碼:
void dp_R(int x, int fa) {
   for(int i = head[x]; i; i = edg[i].nxt) {
     if(edg[i].v == fa) continue;
     dp_R(edg[i].v, x);
     if(edg[i].w + f[edg[i].v][1] > f[x][1]) 
       f[x][2] = f[x][1], f[x][1] = edg[i].w + f[edg[i].v][1];
     else if(edg[i].w + f[edg[i].v][1] > f[x][2])
       f[x][2] = f[edg[i].v][1] + edg[i].w;
     ans = max(f[x][1] + f[x][2], ans);
   }
   }
相關文章
相關標籤/搜索