HDU 2196-コンピューター(クラシックツリーDP)

トピックリンク:

http://acm.hdu.edu.cn/showproblem.php?pid=2196

コンピューター

制限時間:1000/1000 MS(Java /その他)メモリ制限:32768/32768 K(Java /その他)
合計送信数:7329受け入れられた送信数:3630


問題の説明
学校が最初のコンピューターを少し前に購入しました(したがって、このコンピューターのIDは1です)。近年、学校はN-1台の新しいコンピューターを購入しました。新しい各コンピューターは、以前に解決されたコンピューターの1つに接続されていました。学校の管理者は、ネットの機能が遅いことを心配しており、i番目のコンピューターが信号を送信する必要がある最大距離Si(つまり、最も遠いコンピューターまでのケーブルの長さ)を知りたいと考えています。この情報を提供する必要があります。 


ヒント:入力例はこのグラフに対応しています。また、グラフから、コンピューター4が1から最も遠いため、S1 = 3であることがわかります。コンピューター4と5は2から最も遠いため、S2 = 2です。コンピューター5は3から最も遠いため、S3です。 = 3. S4 = 4、S5 = 4も取得します。
 

入力
入力ファイルには複数のテストケースが含まれています。いずれの場合も、最初の行には自然数N(N <= 10000)があり、その後にコンピューターの説明を含む(N-1)行が続きます。i番目の行には、2つの自然数が含まれています。i番目のコンピューターが接続されているコンピューターの数と、接続に使用されているケーブルの長さです。ケーブルの全長は10 ^ 9を超えません。入力行の数字はスペースで区切られます。
 

出力
いずれの場合も、N行を出力します。i番目の行には、i番目のコンピューター(1 <= i <= N)の番号Siが含まれている必要があります。
 

サンプル入力
  
   
   
5 1 1 2 1 3 1 1 1
 

サンプル出力
  
   
   
3 2 3 4 4
 
アイデアは、ツリーの各ポイントからすべての葉のノードまでの距離の最大値を見つけることです。


//经典树形DP
//进行第一次dfs,先以1为根,求出每个节点以该节点为根的子树的最大值和第二大的值
//进行第二次dfs, 对于每个节点v的最大值与第二大值,可能是来自自己的子树或者父节点来的
//判断它来自哪,这取决于该节点v父亲fa[v]取的最大值是来自哪个节点book[v]
//如果book[v]==v,说明fa[v]取的最大值来源于节点v,所以v节点的最大值来源不能是fa[v]的最大值,只能来源于fa[v]第二大或者它的子节点
//如果book[v]!=v, 说明fa[v]取的最大值不是来源于节点v,所以v节点的最大值来源可以是fa[v]的最大值也可以是它的子节点,找最大的
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define maxn 10005
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

struct node
{
	int v, w;
};

vector<node>G[maxn];
ll dp[maxn][2];                     //0是最大,1是第二大
int fa[maxn];                       //父亲
int book[maxn];                     //book[i]表示节点i的最大距离的路径经过的第一个点
//ll num[maxn];//存最终结果
//int vis[maxn];

void dfs1(int root)
{
	int l = G[root].size();
	for(int i=0; i<l; i++)
	{
		int to = G[root][i].v;
		dfs1(to);
	}

	//找第一大
	int num1 = 0;
	for(int i=0; i<l; i++)
	{
		node to = G[root][i];
		if(dp[root][0] < dp[to.v][0]+to.w)
		{
			num1 = i;
			dp[root][0] = dp[to.v][0]+to.w;
			book[root] = to.v;
		}
	}
	//找第二大
	for(int i=0; i<l; i++)
	{
		node to = G[root][i];
		if(dp[root][1] < dp[to.v][0]+to.w && num1!=i)
		{
			dp[root][1] = dp[to.v][0]+to.w;
		}
	}

}

void dfs2(int root, int cnt)            //cnt表示root是它父节点的第cnt个孩子
{
    if(root!=1)
    {
    if(book[fa[root]]!=root)
    {
        if(dp[fa[root]][0]+G[fa[root]][cnt].w > dp[root][0])
        {
            dp[root][1] = dp[root][0];
            dp[root][0] = dp[fa[root]][0]+G[fa[root]][cnt].w;
            //printf("fsafa== %d\n", dp[root][0]);
            book[root] = fa[root];
        }
        else
        {
            dp[root][1] = max(dp[root][1],dp[fa[root]][0]+G[fa[root]][cnt].w);
        }
    }
    else
    {
        if(dp[fa[root]][1]+G[fa[root]][cnt].w > dp[root][0])
        {
            dp[root][1] = dp[root][0];
            dp[root][0] = dp[fa[root]][1]+G[fa[root]][cnt].w;
            book[root] = fa[root];
        }
        else
        {
            dp[root][1] = max(dp[root][1],dp[fa[root]][1]+G[fa[root]][cnt].w);
        }
    }
    }
    int l = G[root].size();
    for(int i=0; i<l; i++)
        dfs2(G[root][i].v, i);
}
/*
void dfs3(int root, int cnt)          //cnt表示root是它父节点的第cnt个孩子
{
	int l = G[root].size();
	for(int i=0; i<l; i++)
	{
		int to = G[root][i].v;
		dfs3(to, i);
	}
    if(root==1)
    {
        num[root] = dp[root][0];
        return;
    }
    if(book[fa[root]]!=root)
    {
        num[root] = max(dp[root][0], dp[fa[root]][0]+G[fa[root]][cnt].w);
    }
    else
    {
        num[root] = max(dp[root][0], dp[fa[root]][1]+G[fa[root]][cnt].w);
    }
}
*/
int main()
{
	int n;
	while(~scanf("%d", &n))
	{
		for(int i=0; i<maxn; i++)
        {
            fa[i] = 0;
            book[i] = 0;
            num[i] = 0;
            dp[i][0] = dp[i][1] = 0;
            G[i].clear();
        }
		for(int i=0; i<n-1; i++)
		{
			int u, w;
			scanf("%d%d", &u, &w);
			G[u].push_back((node){i+2, w});
			//G[i+2].push_back((node){u, w});
			fa[i+2] = u;
		}
//		printf("yes\n");
		dfs1(1);
//		printf("yes1\n");
		dfs2(1,0);
//		printf("yes2\n");
//		dfs3(1,0);
//		printf("yes3\n");
		for(int i=1; i<=n; i++)
		{
		   // printf("dp[%d][0] = %lld\n", i, dp[i][0]);
		    //printf("dp[%d][1] = %lld\n", i, dp[i][1]);
		    //printf("book[%d] = %d\n", i, book[i]);
			printf("%lld\n", dp[i][0]);
		}
	}
	return 0;
}


おすすめ

転載: blog.csdn.net/qq_31281327/article/details/76599294