首页 > 其他分享 >HDU 2196 Computer(树形DP) 入门模板

HDU 2196 Computer(树形DP) 入门模板

时间:2023-04-04 10:08:40浏览次数:47  
标签:HDU int head 距离 edge Computer 2196 节点 dp


Computer

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 34313    Accepted Submission(s): 5345

 

Problem Description

A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information.

HDU 2196 Computer(树形DP)  入门模板_子树

Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.

 

 

Input

Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.

 

 

Output

For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).

 

 

Sample Input

5

1 1

2 1

3 1

1 1

 

 

Sample Output

3

2

3

4

4

 

 

Author

scnu

 

 

Recommend

lcy   |   We have carefully selected several similar problems for you:  1561 1011 3456 1520 2242 

 

算法分析

求一个树中所有节点能到达的最远距离f[i]。要用两个dfs。

首先第一个dfs求出所有每个节点i在其子树中的正向最大距离(dp[i][0])和正向次大距离(dp[i][1])(如果i节点在子树中最大距离经过了2号儿子,那么次大距离就是不经过2号儿子的最大距离)。

由上步我们获得了正向最大距离,正向次大距离和最大距离的儿子节点标记。画图可以知道我们建立的这棵树,i节点的最远距离只有两种选择:i节点所在子树的最大距离,或者i节点连接它的父节点所能到达的最大距离。(即前者往下走,后者先往上走之后很可能也往下走)

所以我们只要求出反向最大距离dp[i][2](即i节点往它的父节点走所能到达的最大距离)就可以知道i节点在整个树中能走的最大距离了。

dp[i][2]求法:i节点往它的父节j点走,如果它的父节点的正向最大距离不经过i的话,那么dp[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向最大距离+ W[i][j].

如果它的父节点的正向最大距离经过i的话,那么dp[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向次大距离+ W[i][j].

上面就是dfs2要求的值。最终f[i] = max(dp[i][0],dp[i][2])


代码不一样,这个简单些

代码实现:

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
struct node
{
	int v;//终端点
    int next;//下一条同样起点的边号
    int w;//权值
}edge[N*2];///无向边,2倍
int head[N];///head[u]=i表示以u为起点的所有边中的第一条边是 i号边
int tot;  ///总边数
void add(int u,int v,int w)
{
	edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int dp[N][3];
void dfs1(int u,int fa)   ///求出每个节点子树下的最大距离和次大距离
{
	 for(int i=head[u];i!=-1;i=edge[i].next)
	 {
	 	int v= edge[i].v;
	    dfs1(v,u);
	    if(fa==v) continue;
	    
	    int t=dp[v][0]+edge[i].w;
	    if(t>dp[u][0])
		{
			dp[u][1]=dp[u][0]; ///原先次短变最短
			dp[u][0]=t;        ///更新最短
		}
		else if(t>dp[u][1])
			dp[u][1]=t;
	 }
}
 void dfs2(int u,int fa)   ///求每一个结点的反向最大距离
 {
 	for(int i=head[u];i!=-1;i=edge[i].next)
	 {
	 	int v= edge[i].v;
	    if(fa==v) continue;
	    
	    if(dp[u][0]==dp[v][0]+edge[i].w)
		{
		 dp[v][2]=max(dp[u][1],dp[u][2])+edge[i].w;
		}
		else
		{
		dp[v][2]=max(dp[u][0],dp[u][2])+edge[i].w;	
		}
		dfs2(v,u);
	 }
	 
 }
int main()
{
  int n;
  while(~scanf("%d",&n))
  {
  	memset(head,-1,sizeof(head));
    memset(dp,0,sizeof(dp));
  	tot=0;
  	for(int v=2;v<=n;v++)
	{
		int u,w;
		scanf("%d%d",&u,&w);
		add(u,v,w);
	}
  	dfs1(1,-1);
  	dfs2(1,-1);
  	 for(int i=1;i<=n;i++)
	printf("%d\n",max(dp[i][0],dp[i][2]));

  }
  
  return 0;
}

双向图:

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
struct node
{
	int v;//终端点
    int next;//下一条同样起点的边号
    int w;//权值
}edge[N*2];///无向边,2倍
int head[N];///head[u]=i表示以u为起点的所有边中的第一条边是 i号边
int tot;  ///总边数
void add(int u,int v,int w)
{
	edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int dp[N][3];
void dfs1(int u,int fa)   ///求出每个节点子树下的最大距离和次大距离
{
	
	if(dp[u][0]>=0) //注意建立双向图,需要有一个标志,来判断是否进入
		return ;     //单向就不用了
	dp[u][0]=0;
	 for(int i=head[u];i!=-1;i=edge[i].next)
	 {
	 	int v= edge[i].v;
	    dfs1(v,u);
	    if(fa==v) continue;
	    
	    int t=dp[v][0]+edge[i].w;
	    if(t>dp[u][0])
		{
			dp[u][1]=dp[u][0]; ///原先次短变最短
			dp[u][0]=t;        ///更新最短
		}
		else if(t>dp[u][1])
			dp[u][1]=t;
	 }
}
 void dfs2(int u,int fa)   ///求每一个结点的反向最大距离
 {
 	for(int i=head[u];i!=-1;i=edge[i].next)
	 {
	 	int v= edge[i].v;
	    if(fa==v) continue;
	    
	    if(dp[u][0]==dp[v][0]+edge[i].w)
		{
		 dp[v][2]=max(dp[u][1],dp[u][2])+edge[i].w;
		}
		else
		{
		dp[v][2]=max(dp[u][0],dp[u][2])+edge[i].w;	
		}
		dfs2(v,u);
	 }
	 
 }
int main()
{
  int n;
  while(~scanf("%d",&n))
  {
  	memset(head,-1,sizeof(head));
    memset(dp,-1,sizeof(dp));
  	tot=0;
  	for(int v=2;v<=n;v++)
	{
		int u,w;
		scanf("%d%d",&u,&w);
		add(u,v,w);
		add(v,u,w);
	}
  	dfs1(1,-1);
  	dfs2(1,-1);
  	 for(int i=1;i<=n;i++)
	printf("%d\n",max(dp[i][0],dp[i][2]));

  }
  
  return 0;
}

 

标签:HDU,int,head,距离,edge,Computer,2196,节点,dp
From: https://blog.51cto.com/u_14932227/6167896

相关文章

  • HDU动态规划题解目录
    ProblemA:MaxSum(HDU1003)   点击这里ProblemB:CommonSubsequence(HDU1159)    点击这里ProblemC:SuperJumping!Jumping!Jumping!(HDU1087)    点击这里ProblemD:HumbleNumbers(HDU1058)   点击这里ProblemE:MonkeyandBanana(HDU1069)    点击这里ProblemF:......
  • hdu - 4578(线段树)
    题目:Yuanfangispuzzledwiththequestionbelow:Therearenintegers,a1,a2,…,an.Theinitialvaluesofthemare0.Therearefourkindsofoperations.Operation1:Addctoeachnumberbetweenaxandayinclusive.Inotherwords,dotransformationak&......
  • HDU 3328 Flipper 栈的应用
    FlipperTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):521    AcceptedSubmission(s):334ProblemDescriptionLittleBobbyRoberts(sonofBigBob,ofProblemG)playsthissolitairememory......
  • hdu3595 GG and MM Every SG博弈
    这是一道很神奇的题,神奇的地方在于全网这个模型只有这题什么是EverySG?不同于普通的ICG,它由多个游戏同时进行,且必须同时进行比如这道题,要求先手一次对所有石头堆都要操作显然对于单独的每种情况,我们都可以求出这是必败态还是必胜态现在摆在我们眼前的就有一堆游戏,对于每个游......
  • hdu3980 Paint Chain SG函数+SG定理+记忆化搜索
    liyishui今天学习博弈,因为liyishui今天写树链剖分写得有点理智--题意:有一个圆,上面有n个豆子,每次要挑出连续m个没染色的豆子进行染色,不能移动时输掉游戏问先手必胜还是后手必胜,其中n、m<=1000题解:会很朴素地想到如果第一个人拿走了m个,那么剩下的就是一条链的问题。所以可以先......
  • 确定比赛名次 HDU - 1285 (拓扑排序)
    题意:有N个比赛队(1≤N≤500),编号依次为1,2,3,...,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比......
  • Transformation HDU - 4578
    题目链接\(1\)题目链接\(2\)题解设一个区间的和、平方和、立方和分别是\(sum_0,sum_1,sum_2\)对于\(add\)操作,推推公式可知\(\begin{cases}newsum_2=sum_2+val^3......
  • hdu-4630(树状数组)
    题目:Lifeisagame,andyouloseit,soyousuicide.Butyoucannotkillyourselfbeforeyousolvethisproblem:Givenyouasequenceofnumbera1,a2,...,an.T......
  • 递推 HDU Problem K 骨牌铺方格
                       骨牌铺方格TimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)TotalSub......
  • dp Problem O:统计问题(HDU 2563)
    ProblemOTimeLimit:3000/1000ms(Java/Other)   MemoryLimit:32768/32768K(Java/Other)TotalSubmission(s):0   AcceptedSubmission(s):0ProblemDescr......