【演演算法分析】——樹與圖的直徑

2020-10-25 15:00:34

在一棵樹中,將任意兩個節點之間最短距離的最大值定義為該樹的直徑。類似地,在一個無向圖中,將任意兩點間最短距離的最大值定義為圖的直徑。

樹的直徑

求樹的直徑一般用兩次bfs解決,當然也可以用兩次dfs,這裡以bfs為例進行說明。先在樹上任選一點A作為起點進行bfs,記錄最後被存取的點B,那麼B離A的距離最遠,再以B為起點進行第二次bfs,即可得到直徑。

#include <bits/stdc++.h>
using namespace std;
int n, vis[100005];
vector<int> g[100005];
void bfs(int start, int &last, int &dist) {
    last = dist = 0;
    queue<pair<int,int>> q;
    memset(vis, 0, sizeof(vis));
    q.push(make_pair(start, 0)); vis[start] = 1;
    while (!q.empty()) {
        pair<int,int> pr = q.front(); q.pop();
        last = pr.first;
        dist = pr.second;
        for (auto i : g[pr.first]) {
            if (!vis[i]) {
                q.push(make_pair(i, pr.second+1));
                vis[i] = 1;
            }
        }
    }
}
int main() {
    cin >> n;
    int x, y, last, dist;
    for (int i = 1; i < n; i++) {
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    bfs(x, last, dist);
    bfs(last, last, dist);
    cout << dist << endl;
    return 0;
}

無向圖的直徑

由於圖可能不連通,且可能有環,不能使用類似樹的方法求解,考慮用更為一般的做法,根據直徑定義,先通過floyd演演算法求出任意兩點間的最短距離,再取最大值即可,注意圖不連通的情況。

#include <bits/stdc++.h>
using namespace std;
int n, m, d[105][105];
const int inf = 0x3f3f3f3f;
int main() {
    memset(d, 0x3f, sizeof(d));
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;
        d[x][y] = d[y][x] = 1;
    }
    for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
    int ans = 0;
    for (int i = 1; i <= n; i++)
    for (int j = i+1; j <= n; j++)
        ans = max(ans, d[i][j]);
    cout << (ans == inf ? -1 : ans) << endl;
    return 0;
}

資源傳送門

  • 關注【做一個柔情的程式猿】公眾號
  • 在【做一個柔情的程式猿】公眾號後臺回覆 【python資料】【2020秋招】 即可獲取相應的驚喜哦!

「❤️ 感謝大家」

  • 點贊支援下吧,讓更多的人也能看到這篇內容(收藏不點贊,都是耍流氓 -_-)
  • 歡迎在留言區與我分享你的想法,也歡迎你在留言區記錄你的思考過程。