ZOJ3684 Destroy 树形DP

两次树形DP

第一次树形DP找中心

如何找到:http://blog.csdn.net/lenleaves/article/details/7784106 看这里


第二次树形dp找最小的能量

设f(x)表示以x为root的子树所有叶子节点到x的路径都已经被切断的最小代价

f(i)=max( min(dist[i][j],f(j))) 其中j是i的儿子节点


Destroy

Time Limit: 2 Seconds       Memory Limit: 65536 KB

DJT country and CG country are always on wars.
This time DJT's King built a new information system over the whole country. He wants to know the message from the frontier immediately. There are numerous cities in DJT. In every city, there is one server of this system, and information is sending to the center continuously along a special data road. However, the data road is so expensive that there is one and only one road from one city to another city. Besides, the place of the center is a secret.

CG, of course, won't let DJT be happy for too long. CG is now planning to destroy DJT's new system. Due to some great undercover agents, CG has controlled some information about DJT's new system. The information CG has got:

  1. The center of DJT's new system would settle down in a city that for all other cities, the maximum distance should be the least.(you can make sure that only one city has the possibility to be the center)
  2. If no frontier city could send message back to the center, the system can be regard as destroyed. (a frontier city is a city that has only one road connecting to it)
  3. The length of each road.
  4. The power we need to destroy each road. (if we have a weapon of power max, we can destroy all the roads which it need the power less or equal to max)

Now, CG gives you a task: calculate the minimum power to destroy the system.

Input

There are multiple cases. For each case, one integer n (0 <= n <= 10000) indicating the number of cities in DJY country, cities are numbered from 1 to n, the next n-1 lines, one line contains four numbers describing one road, the two cities connected by the road, the length, and the power needed to destroy. The lengths are less than or equal to 10000. The powers are less than or equal to 100000000. All integers are nonnegative.

Output

For each case, output one number indicating the least power we need.

Sample Input
9
1 4 1 3
2 3 1 7
2 5 1 2
4 5 1 5
5 6 1 4
5 8 1 4
6 9 1 4
7 8 1 6
Sample Output
4




#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;
const int  MAXN =10000+10;

int n;
int first[MAXN],from[MAXN];
int second[MAXN];
int fat[MAXN];
int ret[MAXN];
bool vis[MAXN];
int head[MAXN],next[MAXN*3],dist[MAXN*3],powe[MAXN*3],to[MAXN*3],en=0;


void add(int a,int b,int c,int d){
    to[en]=b;
    dist[en]=c;
    powe[en]=d;
    next[en]=head[a];
    head[a]=en++;
}

void dfs1(int u){
    first[u]=0;
    from[u]=0;
    second[u]=0;
    vis[u]=1;
    for(int i=head[u];i!=-1;i=next[i]){
        int v=to[i];
        if(vis[v]) continue;
        dfs1(v);
        if(first[v]+dist[i]>=first[u]){
            second[u]=first[u];
            first[u]=first[v]+dist[i],from[u]=v;
        }else if(first[v]+dist[i]>second[u])
            second[u]=first[v]+dist[i];
    }
}

void dfs2(int u,int fa,int dis){
    if(from[fa]!=u)
        fat[u]=max(fat[fa],first[fa])+dis;
    else
        fat[u]=max(fat[fa],second[fa])+dis;
    vis[u]=1;
    for(int i=head[u];i!=-1;i=next[i]){
        int v=to[i];
        if(vis[v]) continue;
        dfs2(v,u,dist[i]);
    }


}

int dp[MAXN];

void dfs3(int u){
    vis[u]=1;
    int ans1=0;
    int ans2=0;
    bool fg=0;
    for(int i=head[u];i!=-1;i=next[i]){
        int v=to[i];
        if(vis[v]) continue;
        fg=1;
        dfs3(v);
        ans2=min(powe[i],dp[v]);
        ans1=max(ans1,ans2);

    }
    if(fg)
        dp[u]=ans1;
    else
        dp[u]=100000000+100;
}

int main(){
    while(~scanf("%d",&n)){
        memset(head,-1,sizeof(head));en=0;
        if(n==0||n==1) printf("0\n");
        for(int i=0;i<n-1;i++){
            int u,v,c,d;
            scanf("%d%d%d%d",&u,&v,&c,&d);
            add(u,v,c,d);
            add(v,u,c,d);
        }
        memset(vis,0,sizeof(vis));
        dfs1(1);
        fat[0]=0;first[0]=0;from[0]=0;second[0]=0;
        memset(vis,0,sizeof(vis));
        dfs2(1,0,0);
        memset(ret,0,sizeof(ret));
        int cent=1,tmp=0x3f3f3f3f;
        for(int i=1;i<=n;i++){
            ret[i]=max(fat[i],first[i]);
            if(ret[i]<tmp)
                tmp=ret[i],cent=i;
        }
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        dfs3(cent);
        printf("%d\n",dp[cent]);
    }
    return 0;

}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值