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;
}


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