2013多校聯合8 1004 Terrorist’s destroy(hdu 4679)

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


Terrorist’s destroy

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 268    Accepted Submission(s): 74


Problem Description
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.
 

Input
The first line contains integer T(1<=T<=20), denote the number of the test cases.
For each test cases,the first line contains a integer n(1 < n <= 100000);denote the number of the houses;
Each of the following (n-1) lines contains third integers u,v,w, indicating there is a road between house u and houses v,and will cost terrorist w energy to destroy it.The id of these road is number from 1 to n-1.(1<=u<=n , 1<=v<=n , 1<=w<=10000)
 

Output
For each test case, output the case number first,and then output the id of the road which the terrorist should destroy.If the answer is not unique,output the smallest id.
 


哎。。。又是賽後5分鐘AC啊。。。傷不起。。。

思路,最後纔想到解法,感覺有點麻煩,調試了半天。。。還是代碼能力不足的結果。

我們隊的方法是首先先設節點1爲根節點,然後設len[i]表示以i節點爲根的子樹中的最長鏈,設dep[i]表示以i爲根節點的子樹中

距離i最遠的節點到i的距離。設maxf[i]表示i的非子節點集中距離i的最遠的點到i的距離。

這三個值可以用普通的樹狀DP解決,這裏就不多說了。


接下來我們dfs從根節點遍歷整棵樹,當我們經過一個節點時,我們枚舉它與它的子節點間的邊,計算刪除這條邊所需的代價,

我們設當前經過的點爲u,它的子節點爲v,設邊v--u的權值爲val,刪除邊u--v後與v相連的那部分子樹的最長鏈顯然爲len[v],現在關鍵是求與u相連的那部分子樹的最長鏈,現在我們假設在dfs遍歷到u時已經將u之上且不與u相連的最長鏈的長度求出,設爲ma,這個可以由dfs從它的父節點傳下來(具體看代碼實現),那麼現在的任務就是求與u相連或者u其他子節點(不包括v)的最長鏈的長度,再和ma比較。便可得到與u相連的子樹中的最長鏈。首先u的其他子節點的最長鏈就是len[x](x是u的子節點且x不爲v),然後求與u相連的最長鏈,我們可以求u的子節點中dep[x]+1最大的兩個(不包括v),設爲m1,m2,然後再加上maxf[u],這三個值裏面去最大的兩個相加即爲所求。這樣我們就得到了與u相連的子樹中的最長鏈,同時我們可以將這個值傳到節點v中,同節點u中的ma。這樣我們就可以通過枚舉,得到所要求的答案。

可能說的有些複雜,但是實現更加複雜。。。。除了上面所講的外,還需要注意些細節,具體實現還是參考代碼吧。

另外注意dfs會爆棧的,可以用#pragma comment(linker, "/STACK:1024000000,1024000000") 。

代碼如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 100010
#define ll long long
using namespace std;
int len[maxn],dep[maxn],maxf[maxn];
struct edge
{
    int to;
    int next;
    int w,id;
}e[maxn<<1];
int box[maxn],cnt=0;
void init(int n)
{
    memset(box,-1,sizeof(int)*n);
    memset(len,0,sizeof(int)*n);
    memset(dep,0,sizeof(int)*n);
    memset(maxf,0,sizeof(int)*n);
    cnt=0;
}
void add(int from,int to,int w,int id)
{
    e[cnt].to=to;
    e[cnt].w=w;
    e[cnt].id=id;
    e[cnt].next=box[from];
    box[from]=cnt++;
}
ll Max;
int ansid;
void dfs1(int now,int fa)
{
    int t,v;
    int m1=0,m2=0;
    for(t=box[now];t+1;t=e[t].next)
    {
        v=e[t].to;
        if(v!=fa)
        {
            dfs1(v,now);
            dep[now]=max(dep[now],dep[v]+1);
            len[now]=max(len[now],len[v]);
            if(dep[v]+1>=m1)
            m2=m1,m1=dep[v]+1;
            else if(dep[v]+1>=m2)
            m2=dep[v]+1;
        }
    }
    len[now]=max(len[now],m1+m2);
}
void dfs2(int now,int fa)
{
    int t,v;
    int m1=0,id1=0,m2=0,id2=0;
    for(t=box[now];t+1;t=e[t].next)
    {
        v=e[t].to;
        if(v!=fa)
        {
           if(dep[v]+1>=m1)
           {
               m2=m1;
               id2=id1;
               m1=dep[v]+1;
               id1=v;
           }
           else if(dep[v]+1>=m2)
           {
               m2=dep[v]+1;
               id2=v;
           }
        }

    }
    for(t=box[now];t+1;t=e[t].next)
    {
         v=e[t].to;
         if(v!=fa)
         {
             if(id1==v)
             {
                 maxf[v]=max(maxf[now],m2)+1;
                 dfs2(v,now);
             }
             else
             {
                 maxf[v]=max(maxf[now],m1)+1;
                 dfs2(v,now);
             }
         }
    }
}
void dfs3(int now,int fa,int ma)
{
    int t,v;
    int m1=0,m2=0,m3=0,id1=0,id2=0;
    for(t=box[now];t+1;t=e[t].next)
    {
        v=e[t].to;
        if(v!=fa)
        {
            if(dep[v]+1>=m1)
            m3=m2,m2=m1,id2=id1,m1=dep[v]+1,id1=v;
            else if(dep[v]+1>=m2)
            m3=m2,m2=dep[v]+1,id2=v;
            else if(dep[v]+1>=m3)
            m3=v;
        }
    }
    int n1=0,pid1=0,n2=0;
    for(t=box[now];t+1;t=e[t].next)
    {
        v=e[t].to;
        if(v!=fa)
        {
            if(len[v]>=n1)
            n2=n1,n1=len[v],pid1=v;
            else if(len[v]>=n2)
            n2=len[v];
        }
    }
    for(t=box[now];t+1;t=e[t].next)
    {
        v=e[t].to;
        if(v!=fa)
        {
            int ans=ma;
            if(v==id1)
            ans=max(ans,max(m2+m3,m2+maxf[now]));
            else if(v==id2)
            ans=max(ans,max(m1+m3,m1+maxf[now]));
            else
            ans=max(ans,max(m1+m2,m1+maxf[now]));
            if(v==pid1)
            ans=max(ans,n2);
            else
            ans=max(ans,n1);
            ll tmp=(ll)max(ans,len[v]);
            if(tmp*e[t].w<Max)
            {
                Max=tmp*e[t].w;
                ansid=e[t].id;
            }
            else if(tmp*e[t].w==Max&&ansid>e[t].id)
            ansid=e[t].id;
            dfs3(v,now,ans);
        }
    }
}
int main()
{
   // freopen("dd.txt","r",stdin);
    int ncase,T=0;
    scanf("%d",&ncase);
    while(ncase--)
    {
        int n,i,x,y,w;
        scanf("%d",&n);
        init(n+1);
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w,i);
            add(y,x,w,i);
        }
        ansid=0;
        Max=(1LL<<62);
        dfs1(1,0);
        dfs2(1,0);
        dfs3(1,0,0);
        printf("Case #%d: %d\n",++T,ansid);
    }
    return 0;
}


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