『树的直径』两次dfs求树的直径

学习树的直径前提须知

树的直径 是一棵树的某两个最深的叶子节点的连线,多用于与图论算法嵌套考算法

算法内容

竞赛须要用到的点

一、很简单的算法,不会单独考,学习和熟练使用它的多种状况学习

树的直径略讲

很简单,两次dfsurl

至于为何,能够画图模拟一下,由于一次dfs必然会在一棵子树或者根节点上,每次dfs必然找到一棵子树的最深的叶子节点,那么第二次dfs必然找到另一棵子树的叶子节点,这两点的惟一路径就是整棵树的直径。由这个定理咱们又能够获得,树的直径不止一条spa

代码以下(参考PT07Z - Longest path in a tree).net

//#define fre yes

#include <cstdio>
#include <cstring>

const int N = 10005;
int head[N << 1], to[N << 1], ver[N << 1];
int d[N];
bool Vis[N];

int tot;
void addedge(int x, int y) {
    ver[tot] = y;
    to[tot] = head[x];
    head[x] = tot++;
}

void dfs(int u) {
    Vis[u] = true;
    for (int i = head[u]; ~i; i = to[i]) {
        int v = ver[i];
        if(!Vis[v]) {
            d[v] = d[u] + 1;
            dfs(v);
        }
    }
}

int diameter(int n) {
    int st = 1, mx = -1e9;

    dfs(st);
    for (int i = 1; i <= n; i++) {
        if(d[i] > mx) {
            mx = d[i];
            st = i;
        }
    }

    memset(d, 0, sizeof(d));
    memset(Vis, false, sizeof(Vis));
    dfs(st);

    mx = -1e9;
    for (int i = 1; i <= n; i++) {
        if(d[i] > mx) {
            mx = d[i];
        }
    } return mx;
}

int main() {
    memset(head, -1, sizeof(head));
    static int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        addedge(u, v);
        addedge(v, u);
    }

    printf("%d\n",diameter(n));
    return 0;
}

那么也就会存在另外一个问题,让你输出你找的两个节点的最短路径code

挺智障的问题,能够在更新完后获得两个节点来搞,也能够在更新时来搞 前者时间消耗多一点,后者空间消耗多一下 看本身喜爱 这里就不放代码了get

相关文章
相关标签/搜索