hdu3534:tree:树的直径问题(dp求解)

题目连接

  • 树形DP专题

题目大意

  • 给出一棵带边权的树;
  • 问1:求出树的直径;
  • 问2:有多少对点的距离等于树的直径。

题目分析

  • 直径的定义: 树上最长的链(可能有多条)。
  • 求树的直径的方法1:用两次dfs来完成
    dfs1从根出发,找到最远的叶子结点 k k k
    dfs2以 k k k 为根,出发,找到离他最远的点 t t t k k k t t t 之间的距离就是直径。
  • 求直径的做法2:dp的思维来实现
    从根出发,搜索的过程中,同时记录最长链与次长链,回溯的时候更新。
  • 本题解抄的就是方法2,而且更巧妙的是,用一个缓存 t m p tmp tmp 来记录可能最长链,节省了一丁点的空间。

解题流程

  • 从根,开始搜索:
  • 回溯到 x x x 的时候 5 个操作:
    • 1 用 t m p tmp tmp 记录经过 y y y 的最长链长度:
      t m p = l e n [ y ] + e ( x , y ) ; tmp=len[y]+e(x,y); tmp=len[y]+e(x,y); 其中 e ( x , y ) e(x,y) e(x,y) ( x , y ) (x,y) (x,y) 之间的边长;
    • 2 如果 a n s < t m p + l e n [ x ] ansans<tmp+len[x] 则更新 链长 a n s ans ans点对 s u m sum sum
      a n s = t m p + l e n [ x ] ; ans=tmp+len[x]; ans=tmp+len[x];
      s u m = n o d [ x ] ∗ n o d [ y ] ; sum=nod[x]*nod[y]; sum=nod[x]nod[y];
    • 3 如果 a n s = = t m p + l e n [ x ] ans==tmp+len[x] ans==tmp+len[x] 则更新 点对 s u m sum sum
      s u m + = n o d [ x ] ∗ n o d [ y ] ; sum+=nod[x]*nod[y]; sum+=nod[x]nod[y];
    • 4 如果 t m p > l e n [ x ] tmp>len[x] tmp>len[x] 则更新 x x x 的参数: l e n [ x ] len[x] len[x] n o d [ x ] nod[x] nod[x]
      l e n [ x ] = t m p ; len[x]=tmp; len[x]=tmp;
      n o d [ x ] = n o d [ y ] ; nod[x]=nod[y]; nod[x]=nod[y];
    • 5 如果 t m p = = l e n [ x ] tmp==len[x] tmp==len[x] 则更新 x x x 的参数: n o d [ x ] nod[x] nod[x]
      n o d [ x ] + = n o d [ y ] ; nod[x]+=nod[y]; nod[x]+=nod[y];
  • 最后答案是: a n s ans ans s u m sum sum

参考代码

//hdu3534-tree
//求直径与其端点的对数 
#include
using namespace std;
const int N=500007;
const int inf=1e9+7;
struct node{
	int nex,to,c;
}e[N];
int n,ans,sum,len[N],nod[N];
int las[N],cnt;
void add(int x,int y,int c){
	cnt++;
	e[cnt].nex=las[x];
	e[cnt].to=y;
	e[cnt].c=c;
	las[x]=cnt;
}
void dfs(int x,int fa){
	len[x]=0;
	nod[x]=1;
	for(int i=las[x];i;i=e[i].nex){
		int y=e[i].to;
		if(y==fa) continue;
		dfs(y,x);
		
		int tmp=e[i].c+len[y]; //求出经过y点的最长链 
		
		if(tmp+len[x]>ans) ans=tmp+len[x],sum=nod[x]*nod[y];
		else if(tmp+len[x]==ans) sum+=nod[x]*nod[y];
		
		if(tmp>len[x]) len[x]=tmp,nod[x]=nod[y];
		else if(tmp==len[x]) nod[x]+=nod[y];
	}
}
int main(){
	while(~scanf("%d",&n)){
		memset(las,0,sizeof(las));
		int x,y,c;
		cnt=0;
		for(int i=1;i<n;i++){
			scanf("%d %d %d",&x,&y,&c);
			add(x,y,c); add(y,x,c);
		}
		ans=-inf;
		sum=0;
		dfs(1,0);
		printf("%d %d\n",ans,sum);
	}
	return 0;
} 

你可能感兴趣的:(树形DP,动态规划,题解)