樹形DP 2013多校8(Terrorist’s destroy HDU4679)

題意:
There is a city which is built like a tree.A terrorist wants to destroy the city's roads. But now he is alone, he can only destroy one road, then the city will be divided into two cities. Impression of the city is a number defined as the distance between the farthest two houses (As it relates to the fare).When the terrorist destroyed a road, he needs to spend some energy, assuming that the number is a.At the same time,he will get a number b which is maximum of the Impression of two cities. The terrorist wants to know which road to destroy so that the product of a and b will be minimized.You should find the road's id.
Note that the length of each road is one.
給出一個樹形圖,和邊權值w代表耗費的能量,每條邊的長度是1;破壞一條邊<u,v>會形成兩棵樹,b是兩個樹中較大的那個直徑,a是<u,v>的能量值,求破壞哪條邊保證a*b的至最小若存在多個,則輸出最先出現的那條邊;
分析:求樹的直徑,我們很容易想到兩個dfs可以求出樹的直徑,所以先樹形dp(前兩個dfs)求出每個點的正向距離的最大值dis[u][0]和次大值dis[u][1],以及反向距離最大值dis[u][2],然後第三個dfs深搜枚舉每條邊的兩個點<u,v>,對於v點,v所對應的子樹的直徑就是
dis[v][0]+dis[v][1];

對於v如果belong[u]==v這u所對應的子樹的直徑是dis[u][1]+dis[u][2];否則對應的子樹直徑是dis[u][0]+dis[u][2];
然後枚舉a*b即可:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"queue"
#include"algorithm"
#include"string.h"
#include"string"
#include"math.h"
#include"vector"
#include"stack"
#include"map"
#define eps 1e-4
#define inf 0x3f3f3f3f
#define M 100009
#define PI acos(-1.0)
using namespace std;
struct node
{
    int u,v,w,next;
}edge[M*2];
int t,head[M],dis[M][4],length[M*2],belong[M];
__int64 ans,num[M],n;
void init()
{
    t=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    edge[t].u=u;
    edge[t].v=v;
    edge[t].w=w;
    edge[t].next=head[u];
    head[u]=t++;
}
void dfs(int u,int f)
{
    dis[u][0]=dis[u][1]=dis[u][2]=0;
    for(int i=head[u];~i;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f)continue;
        dfs(v,u);
        if(dis[u][0]<dis[v][0]+1)
        {
            dis[u][1]=dis[u][0];
            dis[u][0]=dis[v][0]+1;
            belong[u]=v;
        }
        else if(dis[u][1]<dis[v][0]+1)
            dis[u][1]=dis[v][0]+1;
    }
}
void dfs1(int u,int f)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f)
            continue;
        if(belong[u]==v)
            dis[v][2]=max(dis[u][1],dis[u][2])+1;
        else
            dis[v][2]=max(dis[u][0],dis[u][2])+1;
        dfs1(v,u);
    }
}
void dfs2(int u,int f)
{
    for(int i=head[u];~i;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f)continue;
        if(belong[u]==v)
        {
            length[i]=dis[v][0]+dis[v][1];
            length[i^1]=dis[u][1]+dis[u][2];
        }
        else
        {
            length[i]=dis[v][0]+dis[v][1];
            length[i^1]=dis[u][0]+dis[u][2];
        }
        dfs2(v,u);
    }
}
int main()
{
    int Case,i,n,a,b,c,kk=1;
    scanf("%d",&Case);
    while(Case--)
    {
        scanf("%d",&n);
        init();
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dfs(1,-1);
        dfs1(1,-1);
        dfs2(1,-1);
        ans=inf;
        int id;
        for(i=0;i<t;i+=2)
        {
            //printf("%d %d %d %d\n",edge[i].u,edge[i].v,length[i],length[i^1]);
            int m=max(length[i],length[i^1])*edge[i].w;
            if(ans>m)
            {
                id=i;
                ans=m;
            }
        }
        printf("Case #%d: %d\n",kk++,(id+2)/2);
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章