Link
题意:
求边权为正的树的直径(树上最长链)
思路:
首先任选一点为根,记为 \(root\) 并记 \(dp[x]\) 为以 \(x\) 为起点与其朝下所有节点的路径最大值
进行一次树形 DP
\(dp[i]=\max \limits_{j \in son(i)}(dp[i],w[i][j]+dp[j])\)
我们可以发现树的直径其实是以某一点为起点的路径长度的最大值与次大值和,且这两条路径没有重复边
因此我们在进行树形 DP从下到上转移时对 \(res\) 进行更新:
\(res=\max \limits_{j \in son(i)}(res,dp[i]+dp[j]+w[i][j])\)
代码:
#include<iostream>
using namespace std;
const int N=4e4+5;
const int M=8e4+5;
int n,m;
int cnt;
int to[M],val[M],nxt[M],head[N];
bool st[N];
int dp[N];
int res;
void addedge(int u,int v,int w) {
cnt++;
to[cnt]=v;
val[cnt]=w;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int u) {
st[u]=true;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i],w=val[i];
if(st[v]) continue;
dfs(v);
res=max(res,dp[u]+dp[v]+w);
dp[u]=max(dp[u],dp[v]+w);
}
}
int main() {
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++) {
int u,v,w;
char c;
cin>>u>>v>>w>>c;
addedge(u,v,w);
addedge(v,u,w);
}
dfs(1);
cout<<res<<endl;
return 0;
}