poj2631 树的直径(两次bfs/树形dp)

poj2631 树的直径(两次bfs/树形dp)_第1张图片poj2631 树的直径(两次bfs/树形dp)_第2张图片

题意

求树的直径,即树上最长的一条路

题解

①两次bfs

②两次dfs,期间更新最大值

③树形dp,因为一个分支节点只能从三个方向更新,最大的那两个方向之和就是该点的最长距离

思路来源及证明部分

http://hzwer.com/2996.html

https://www.cnblogs.com/a-clown/p/6131346.html

代码

①树形dp

#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
const int INF=0x3f3f3f3f;
const int maxn=2e6+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector 
#define si set
#define pii pair 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std; 
struct edge
{
	int to,nex,w;
}e[maxn]; 
int head[maxn],cnt; 
//dp[u][0]代表最长
//dp[u][1]代表次长
void add(int u,int v,int w)
{
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].nex=head[u];
	head[u]=cnt++;
}
int ans,dp[maxn][2]; 
void init()
{
	mem(head,-1);
	cnt=0;
}
void dfs(int u,int fa)
{
	for(int i=head[u];~i;i=e[i].nex)
	{
		int v=e[i].to,w=e[i].w;
		if(v==fa)continue;
		dfs(v,u);
		if(dp[v][0]+w>dp[u][0])
		{
			dp[u][1]=dp[u][0];
			dp[u][0]=dp[v][0]+w;
		}
		else dp[u][1]=max(dp[u][1],dp[v][0]+w);
	}
	ans=max(ans,dp[u][0]+dp[u][1]);
}
int main()
{ 
   int u,v,w;
   init();
   while(~scanf("%d%d%d",&u,&v,&w))
   add(u,v,w),add(v,u,w);
   dfs(1,-1);
   printf("%d\n",ans);
   return 0;
}

②两次dfs

#include 
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
const int INF=0x3f3f3f3f;
const int maxn=2e6+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector 
#define si set
#define pii pair 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std; 
struct edge
{
	int to,nex,w;
}e[maxn]; 
int head[maxn],cnt; 
void add(int u,int v,int w)
{
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].nex=head[u];
	head[u]=cnt++;
}
int to,tmp; 
void init()
{
	mem(head,-1);
	cnt=0;
}
void dfs(int u,int fa,int dis)
{
	if(dis>tmp)tmp=dis,to=u;
	for(int i=head[u];~i;i=e[i].nex)
	{
		int v=e[i].to,w=e[i].w;
		if(v==fa)continue;
		dfs(v,u,dis+w);
	}
}
int main()
{ 
   int u,v,w;
   init();
   while(~scanf("%d%d%d",&u,&v,&w))
   add(u,v,w),add(v,u,w);
   dfs(1,-1,0);
   tmp=0;
   dfs(to,-1,0);
   printf("%d\n",tmp);
   return 0;
}

 

你可能感兴趣的:(树形dp)