1509: [NOI2003]逃学的小孩
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 646 Solved: 338
[ Submit][ Status][ Discuss]
Description

Input
第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1Ui, Vi N,1 Ti 1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。
Output
仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。
Sample Input
4 3
1 2 1
2 3 1
3 4 1
1 2 1
2 3 1
3 4 1
Sample Output
4
HINT
Source
在树上找3个点 x,y,z满足 xy<xz 且xy+yz最大
通过2遍dfs求得树的直径
ACcode:
#include <bits/stdc++.h>
#define maxn 200002
#define ll long long
#define mv (my[i].to)
using namespace std;
int n,m;
ll dp[maxn][4],ans;
struct edge {int to,w,next;}my[maxn << 1];
int head[maxn],tot;
inline void init(){memset(head,-1,sizeof(head));tot=0;memset(dp,0,sizeof(dp));}
inline void add(int u,int v,int w){my[tot].to=v;my[tot].next=head[u];my[tot].w=w;head[u]=tot++;}
inline void dfs1(int x,int fa=-1) {
dp[x][0]=dp[x][1]= 0;
for(int i=head[x];i!=-1;i=my[i].next)if(my[i].to!=fa){
dfs1(mv,x);
dp[x][2] = max(dp[x][2], dp[mv][0]+my[i].w);
if(dp[x][2]>dp[x][1]) swap(dp[x][2],dp[x][1]);
if(dp[x][1]>dp[x][0]) swap(dp[x][0],dp[x][1]);
}
}
inline void dfs2(int x,int fa=-1){
for(int i=head[x];i!=-1;i=my[i].next)if(my[i].to!=fa){
dp[mv][3]=max(dp[x][3],dp[mv][0]+my[i].w==dp[x][0]?dp[x][1]:dp[x][0])+my[i].w;
dfs2(mv,x);
}
}
inline void upd(ll &x, ll &y, ll &z) {
if(y > x) swap(x, y);
if(z > x) swap(x, z);
if(z > y) swap(y, z);
ans = max(x + (y << 1) + z, ans);
}
int main(){
init();
cin>>n>>m;
for(;m--;){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);add(b,a,c);
}
dfs1(1);dp[1][3]=0;dfs2(1);
ans=0;
for(int i=1;i<=n;i++)
dp[i][3]<=dp[i][2] ?upd(dp[i][0],dp[i][1],dp[i][2]):upd(dp[i][0],dp[i][1],dp[i][3]);
cout<<ans<<'\12';
return 0;
}