程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu-4679-Terrorist’s destroy

hdu-4679-Terrorist’s destroy

編輯:C++入門知識

題意:

有一顆樹,卻掉一條邊花費的費用為:去掉這條邊後生成的兩棵樹的最大直徑*這條邊的權值。

讓你求去掉哪條邊,花費的費用最小。輸出邊號。

做法:
可以枚舉刪掉的邊,通過記錄一些值,dp求出刪掉此邊後剩下兩棵樹
的直徑。
首先一遍dfs求出以U為根的子樹直徑f[U],以及子樹中距離U最長的點和U的距離,和它是由U的哪個兒子得到; 同時記錄一個次大的,再記錄一個次次大的。
然後第二遍dfs,求出除去以U為根的子樹後,剩下的子樹的直徑h[U]。


如上圖:假設已經得到h[U] 了(h[ROOT] = 0),現在要求出除去以V為根的子樹後,剩下樹的直徑h[V],那麼h[V] 可能由四個方面得到:
1. 2中h[U]。
2. 1中U的兒子的f 最大值。
3. 1中從U的兒子出發的一條最長的鏈+2中從FA出發的一條最長鏈+2(2中從FA出發的一條最長鏈,可以單獨維護得到)。
4. 1中從U的兒子出發的一條最長的鏈+1中從U的兒子出發的一條
次長鏈+2。


代碼:

 

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
#define maxn 100011
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define INF 99999999
struct list
{
    int u,v,w,number;
    int next;
} node[maxn*4];
struct list2
{
    int point;
    int len;
}no[4][maxn],pp;
int head[maxn*10];
int low[maxn*2];
int f[maxn];
int ipf[maxn][2];
int ips[maxn][2];
int h[maxn];
int tops,maxx,ipos,n;
void add(int u,int v,int w,int number)
{
    node[tops].u=u;
    node[tops].v=v;
    node[tops].w=w;
    node[tops].number=number;
    node[tops].next=head[u];
    head[u]=tops++;
}
void init()
{
    memset(head,-1,sizeof(head));
    memset(f,0,sizeof(f));
    memset(h,0,sizeof(h));
    memset(ipf,0,sizeof(ipf));
    memset(low,0,sizeof(low));
    memset(ips,0,sizeof(ips));
    tops=0;
    maxx=INF;
    ipos=maxn+10;
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
    {
        no[1][i].len=no[2][i].len=no[3][i].len=0;
        no[1][i].point=no[2][i].point=no[3][i].point=0;
    }
    int a,b,c;
    for(int i=1; i<n; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c,i);
        add(b,a,c,i);
    }
}
int dfs(int x,int pre)
{
    int ts,tt;
    ts=0;
    f[x]=0;
    for(int i=head[x]; i!=-1; i=node[i].next)
    {
        int y=node[i].v;
        if(y==pre)continue;
        tt=dfs(y,x)+1;
        ts=max(tt,ts);
        if(f[y]>=ipf[x][0])
        {
            ipf[x][1]=ipf[x][0];
            ipf[x][0]=f[y];
            ips[x][1]=ips[x][0]=y;
        }
        else if(f[y]>=ipf[x][1])
        {
            ipf[x][1]=f[y];
        }
        f[x]=max(f[x],f[y]);
        pp.point=y;
        pp.len=tt;
        for(int j=1; j<=3; j++)
            if(no[j][x].len<=tt)
            {
                for(int k=3; k>=j+1; k--)
                {
                    no[k][x]=no[k-1][x];
                }
                no[j][x]=pp;
                break;
            }

    }
    int ds=no[1][x].len+no[2][x].len;
    f[x]=max(f[x],ds);
    return ts;
}
int chu(int pre,int x,int y)
{
    int s1,s2,s3,s4;
    int leap=0;
    s1=s2=s3=s4=0;
    if(ips[x][0]!=y)s1=ipf[x][0];
    else s1=ipf[x][1];
    if(no[1][x].point!=y)s2=no[1][x].len,leap++;
    if(no[2][x].point!=y)s2+=no[2][x].len,leap++;
    if(no[3][x].point!=y&&leap==1)s2+=no[3][x].len,leap++;
    s3=h[x];
    if(no[1][pre].point!=x)s4=no[1][pre].len;
    else s4=no[2][pre].len;
    s4=max(s4,low[pre]);
    if(no[1][x].point!=y)s4+=no[1][x].len;
    else s4+=no[2][x].len;
    if(pre!=0)s4++;
    return max(max(s1,s2),max(s3,s4));

}
void spfa(int x,int pre)
{
    int visit[maxn];
    memset(visit,0,sizeof(visit));
    queue<int>q;
    queue<int>qp;
    q.push(x);
    qp.push(pre);
    visit[x]=1;
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        pre=qp.front();
        qp.pop();
        for(int i=head[x]; i!=-1; i=node[i].next)
        {
            int y=node[i].v;
            if(y==pre)continue;
            h[y]=chu(pre,x,y);
            int ss=max(h[y],f[y])*node[i].w;
            if(ss<maxx)
            {
                maxx=ss;
                ipos=node[i].number;
            }
            else if(ss==maxx)ipos=min(ipos,node[i].number);
            q.push(y);
            qp.push(x);
        }
    }
}
void panlow(int x,int pre)
{
    for(int i=head[x]; i!=-1; i=node[i].next)
    {
        int y=node[i].v;
        if(y==pre)continue;
        if(y!=no[1][x].point)
        {
            low[y]=max(no[1][x].len+1,low[x]+1);
        }
        else low[y]=max(no[2][x].len+1,low[x]+1);
        panlow(y,x);
    }

}
int main()
{
    int t,T;
   // freopen("in.txt","r",stdin);
    scanf("%d",&T);
    for(t=1; t<=T; t++)
    {
        init();
        //cout<<"initover"<<endl;
        if(dfs(1,0));
       // cout<<"dfsover"<<endl;
        panlow(1,0);
        spfa(1,0);
        printf("Case #%d: %d\n",t,ipos);
    }
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved