bzoj 1509 逃学的小孩

本文提供了一道NOI2003竞赛题“逃学的小孩”的详细解答过程,该题旨在寻找树状结构中三个特定点以最大化路径长度之和。文章分享了使用两遍深度优先搜索(DFS)来确定树直径的方法,并附上了完整的C++代码实现。

1509: [NOI2003]逃学的小孩

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 646   Solved: 338
[ Submit][ Status][ Discuss]

Description

Input

第一行是两个整数N(3  N  200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1Ui, 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

Sample Output

4

HINT

Source

[ Submit][ Status][ Discuss]


HOME Back

在树上找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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值