POJ 1985.Cow Marathon(DFS求树的直径模板题)

两次BFS/DFS求树的直径

我们可以先从任意一点开始DFS,记录下当前点所能到达的最远距离,这个点为P。

在从P开始DFS记录下所能达到的最远点的距离,这个点为Q。

\(P , Q\)就是直径的端点,\(d i s ( P , Q )\)就是直径。
具体代码见下题

题意:有N个农田以及M条路,给出M条路的长度以及路的方向(这道题不影响,用不到),让你找到一条 两农田(任意的)间的路径,使得距离最长,并输出最长距离。
这里用dfs求直径,当然也可以用bfs和树形DP来做。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define over(i,s,t) for(register int i = s;i <= t;++i)
#define lver(i,t,s) for(register int i = t;i >= s;--i)
using namespace std;
const int N = 5e5 + 7;
const int M = 2007;

int head[N], ver[N], tot, edge[N], nex[N];
int n, m, ans;
int dis[N], vis[N];

inline void add(int u, int v, int w) {
    ver[++tot] = v;
    edge[tot] = w;
    nex[tot] = head[u];
    head[u] = tot;
}

//两次dfs一次求P一次求Q
void dfs(int u, int& ed) {
    if (dis[u] > ans)ans = dis[u], ed = u;
    vis[u] = 1;
    for (int i = head[u]; ~i; i = nex[i]) {
        int v = ver[i], w = edge[i];
        if (vis[v])continue;
        dis[v] = dis[u] + w;
        dfs(v, ed);
    }
    return;
}

int p, q;
void solve() {
    dfs(1, p);//第一遍DFS求当下点能达到的最大距离
    ans = dis[p] = 0;
    memset(vis, 0, sizeof vis);
    dfs(p, q);//第二遍DFS求从p开始能达到的最远距离
    //p,q的距离就是最大距离了,即 ans
    cout << ans << endl;
}
int main()
{
    while (scanf("%d%d", &n, &m) != EOF) {
        memset(head, -1, sizeof head);
        memset(vis, 0, sizeof vis);
        memset(dis, 0, sizeof dis);
        tot = 0;
        over(i, 1, m) {
            int u, v, w;
            char ch[2];
            scanf("%d%d%d%s", &u, &v, &w, ch);
            add(u, v, w);
            add(v, u, w);
        }
        solve();
    }
    return 0;
}
posted @ 2020-09-14 19:51  RioTian  阅读(130)  评论(0编辑  收藏  举报