POJ 1985.Cow Marathon(DFS求樹的直徑模板題)
阿新 • • 發佈:2020-09-14
兩次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; }