1. 程式人生 > >[hihocoder 1050]求樹的最長鏈

[hihocoder 1050]求樹的最長鏈

c++ mes clu 最長 logs amp tor 樹形dp target

題目鏈接:http://hihocoder.com/problemset/problem/1050

兩種方法:

1. 兩遍dfs,第一次隨便找一個根,找到距離這個根最遠的點,這個點必然是最長鏈的一端。第二次就用這個端點做一遍dfs,最遠的點就是另一端。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int d[maxn];
vector<int> G[maxn];

void dfs(int u,int fa,int now)
{
    d[u]=now;
    for (int i=0;i<G[u].size();i++)
    {
        
int v=G[u][i]; if (v!=fa) dfs(v,u,now+1); } } int main() { int n; scanf("%d",&n); for (int i=0;i<n-1;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0,0); int ma=0,maj=1; for (int
i=1;i<=n;i++) { if (d[i]>ma) { ma=d[i]; maj=i; } } dfs(maj,0,0); int ans=0; for (int i=1;i<=n;i++) ans=max(ans,d[i]); printf("%d",ans); return 0; }

2. 樹形dp。記dp[i][0/1]表示以i為lca的最長鏈和次長鏈的長度,一遍dfs更新就好了。

#include<bits/stdc++.h>
using
namespace std; const int maxn=100005; int dp[maxn][2]; vector<int> G[maxn]; void dfs(int u,int fa) { for (int i=0;i<G[u].size();i++) { int v=G[u][i]; if (v!=fa) dfs(v,u); } if (G[u].size()<=2) { for (int i=0;i<G[u].size();i++) { int v=G[u][i]; if (v!=fa) dp[u][0]=dp[v][0]+1; } } else { for (int i=0;i<G[u].size();i++) { int v=G[u][i]; if (v!=fa) { if (dp[v][0]+1>dp[u][0]) { dp[u][1]=dp[u][0]; dp[u][0]=dp[v][0]+1; } else dp[u][1]=max(dp[v][0]+1,dp[u][1]); } } } } int main() { int n; scanf("%d",&n); G[1].push_back(0); for (int i=0;i<n-1;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); int ans=0; for (int i=1;i<=n;i++) ans=max(ans,dp[i][0]+dp[i][1]); printf("%d",ans); return 0; }

[hihocoder 1050]求樹的最長鏈