木の直径と例

木の直径

ツリー上の任意の 2 つのノード間の最長の単純なパスは、ツリーの「直径」です。
2 つの深さ優先検索または動的計画法で解決可能

2回のDFS

まず、最初の DFS を任意のノード y から開始し、そこから最も遠いノード (z として記録される) に到達し、次に z から開始して 2 番目の DFS を実行し、z から最も遠いノードに到達します (z' として記録されます)。の場合、\ delta(z,z') は木の直径になります。
明らかに、最初の DFS が到達するノード z が直径の一端である場合、2 番目の DFS が到達するノード z' は直径の一端でなければなりません。どのような場合でも z が直径の一端でなければならないことを示すだけで済みます。
定理: ツリー上で、任意のノード y から DFS を開始し、到達した最も遠いノード z が直径の一端でなければなりません。

const int N = 10000 + 10;

int n, c, d[N];
vector<int> E[N];

void dfs(int u, int fa) {
    
    
  for (int v : E[u]) {
    
    
    if (v == fa) continue;
    d[v] = d[u] + 1;
    if (d[v] > d[c]) c = v;
    dfs(v, u);
  }
}

int main() {
    
    
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    
    
    int u, v;
    scanf("%d %d", &u, &v);
    E[u].push_back(v), E[v].push_back(u);
  }
  dfs(1, 0);
  d[c] = 0, dfs(c, 0);
  printf("%d\n", d[c]);
  return 0;
}

ツリーDP

1 がツリーのルートであるとき、サブツリーのルートである各ノードが下に行くにつれて、延長できる最長のパスの長さ d_1 と 2 番目に長いパス (最長のパスと共通のエッジがない) の長さ d_2 を記録します。各点について、この点での d_1 + d_2 の最大値を取得できます。
Tree DP は、負の重み付けエッジが存在する場合でも木の直径を解決できます。

const int N = 10000 + 10;

int n, d = 0;
int d1[N], d2[N];
vector<int> E[N];

void dfs(int u, int fa) {
    
    
  d1[u] = d2[u] = 0;
  for (int v : E[u]) {
    
    
    if (v == fa) continue;
    dfs(v, u);
    int t = d1[v] + 1;
    if (t > d1[u])
      d2[u] = d1[u], d1[u] = t;
    else if (t > d2[u])
      d2[u] = t;
  }
  d = max(d, d1[u] + d2[u]);
}

int main() {
    
    
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    
    
    int u, v;
    scanf("%d %d", &u, &v);
    E[u].push_back(v), E[v].push_back(u);
  }
  dfs(1, 0);
  printf("%d\n", d);
  return 0;
}

1 から n までの番号が付けられた n 個の都市が与えられます。同時に、サイズ n-1 の配列エッジを与えます。ここで、edges[i] = [ui, vi] は、都市 ui と vi の間に双方向のエッジがあることを意味します。タイトルは、どの都市間にも 1 本の経路しかないことを保証します。言い換えれば、すべての都市がツリーを形成します。
サブツリーは都市のサブセットであり、サブセット内のどの都市にも、サブセット内の他の都市やエッジを介して到達できます。少なくとも 1 つの都市が一方のサブツリーに存在し、もう一方のサブツリーには存在しない場合、2 つのサブツリーは異なるものとみなされます。
1 から n-1 までの d について、都市間の最大距離が正確に d であるすべてのサブツリーの数を見つけてください。
サイズ n-1 の配列を返してください。ここで、d 番目の要素 (添字は 1 から始まります) は、都市間の最大距離が d に正確に等しいサブツリーの数です。
2 つの都市間の距離は、都市間を通過する必要があるエッジの数として定義されることに注意してください。

例 1:
入力: n = 4、エッジ = [[1,2],[2,3],[2,4]]
出力: [3,4,0]
説明:
サブツリー {1,2}, { 2 ,3} と {2,4} の最大距離は 1 です。
サブツリー {1,2,3}、{1,2,4}、{2,3,4}、および {1,2,3,4} の最大距離はすべて 2 です。
都市間の最大距離が 3 のサブツリーはありません。

例 2:
入力: n = 2、エッジ = [[1,2]]
出力: [1]

例 3:
入力: n = 3、エッジ = [[1,2],[2,3]]
出力: [2,1]

ヒント:
2 <= n <= 15edges.length
== n-1edges
[i].length == 2
1 <= ui, vi <= n
タイトルは、(ui, vi) で表されるエッジが異なることを保証します。互いに。

class Solution {
    
    
public:      
    vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
    
    
        vector<vector<int>> adj(n);        
        for (auto &edge : edges) {
    
    
            int x = edge[0] - 1;
            int y = edge[1] - 1;
            adj[x].emplace_back(y);
            adj[y].emplace_back(x);
        }

        function<int(int, int, int)> dfs = [&](int parent, int u, int mask)->int {
    
    
            int depth = 0;
            for (int v : adj[u]) {
    
    
                if (v != parent && mask & (1 << v)) {
    
    
                    depth = max(depth, 1 + dfs(u, v, mask));
                }
            }
            return depth;
        };

        vector<int> ans(n - 1);
        for (int i = 1; i < (1 << n); i++) {
    
    
            int x = 32 - __builtin_clz(i) - 1;
            int mask = i;
            int y = -1;
            queue<int> qu;
            qu.emplace(x);
            mask &= ~(1 << x);
            while (!qu.empty()) {
    
    
                y = qu.front();
                qu.pop();
                for (int vertex : adj[y]) {
    
    
                    if (mask & (1 << vertex)) {
    
    
                        mask &= ~(1 << vertex);
                        qu.emplace(vertex);
                    }
                }
            }
            if (mask == 0) {
    
    
                int diameter = dfs(-1, y, i);
                if (diameter > 0) {
    
    
                    ans[diameter - 1]++;
                }
            }
        }
        return ans;
    }
};

おすすめ

転載: blog.csdn.net/weixin_45184581/article/details/129473198