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;
}