HDU 5956 The Elder(树上斜率优化DP)

版权声明:转载请注明出处:http://blog.csdn.net/yasola,谢谢 https://blog.csdn.net/Yasola/article/details/78659854

The Elder

Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1098 Accepted Submission(s): 289

Problem Description
Once upon a time, in the mystical continent, there is a frog kingdom, ruled by the oldest frog, the Elder. The kingdom consists of N cities, numbered from east to west. The 1-th city, which is located to the east of others, is the capital. Each city, except the capital, links none or several cities to the west, and exactly one city to the east.
There are some significant news happening in some cities every day. The Elder wants to know them as soon as possible. So, that is the job of journalist frogs, who run faster than any other frog. Once some tremendous news happen in a city, the journalist in that city would take the message and run to the capital. Once it reach another city, it can either continue running, or stop at that city and let another journalist to transport. The journalist frogs are too young and simple to run a long distance efficiently. As a result, it takes L2 time for them to run through a path of length L. In addition, passing message requires P time for checking the message carefully, because any mistake in the message would make the Elder become extremely angry.
Now you are excited to receive the task to calculate the maximum time of sending a message from one of these cities to the capital.

Input
The first line of input contains an integer t, the number of test cases. t test cases follow. For each test case, in the first line there are two integers N (N ≤ 100000) and P (P ≤ 1000000). In the next N-1 lines, the i-th line describes the i-th road, a line with three integers u,v,w denotes an edge between the u-th city and v-th city with length w(w ≤ 100).

Output
For each case, output the maximum time.

Sample Input
3
6 10
1 2 4
2 3 5
1 4 3
4 5 3
5 6 3
6 30
1 2 4
2 3 5
1 4 3
4 5 3
5 6 3
6 50
1 2 4
2 3 5
1 4 3
4 5 3
5 6 3

Sample Output
51
75
81
Hint
In the second case, the best transportation time is:
• The 2-th city: 16 = 4^2
• The 3-th city: 72 = 4^2 + 30 + 5^2
• The 4-th city: 9 = 3^2
• The 5-th city: 36 = (3 + 3)^2
• The 6-th city: 75 = (3 + 3)^2 +30 + 3^2
Consequently, the news in the 6-th city requires most time to reach the capital.

Source
2016ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

Recommend
jiangzijing2015

题目大意

  有一颗带边权的树,长者住在一号节点,其它节点都有一些记者要给长者送大新闻,每个记者走长度为x的边的花费为x2,在节点处可以换记者花费为P,每个地点都采取最优的策略,求花费最大的点的花费。

解题思路

  显然树上DP,然后这个转移方程就是最经典的斜率优化DP的形式。那么从跟节点往下dfs,对每条链进行斜率优化DP,回溯的时候恢复一下单调队列即可。

AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define LL long long
#define fi first
#define se second

const LL MAXV=100000+3;
LL V, P, ans;
vector<pair<LL, LL>> G[MAXV];
LL que[MAXV], head, tail;
LL dp[MAXV], dist[MAXV];

void init()
{
    for(LL i=1;i<=V;++i)
        G[i].clear();
    ans=P;
    head=tail=0;
}

inline LL get_up(LL j, LL k)
{
    return dp[j]-dp[k]+dist[j]*dist[j]-dist[k]*dist[k];
}

inline LL get_down(LL j, LL k)
{
    return 2*(dist[j]-dist[k]);
}

inline LL get_dp(LL i, LL j)
{
    return dp[j]+(dist[i]-dist[j])*(dist[i]-dist[j])+P;
}

void dfs1(LL u, LL fa)
{
    for(LL i=0;i<G[u].size();++i)
    {
        LL v=G[u][i].fi;
        if(v==fa)
            continue;
        dist[v]=dist[u]+G[u][i].se;
        dfs1(v, u);
    }
}

void dfs2(LL u, LL fa)
{
    LL save_head=head, save_tail=tail;
    for(LL i=0;i<G[u].size();++i)
    {
        LL v=G[u][i].fi;
        if(v==fa)
            continue;
        while(head+1<tail && get_up(que[head+1], que[head]) <= dist[v]*get_down(que[head+1], que[head]))
            ++head;
        dp[v]=get_dp(v, que[head]);
        ans=max(ans, dp[v]);
        vector<LL> save;
        while(head+1<tail && get_up(v, que[tail-1])*get_down(que[tail-1], que[tail-2]) <= get_up(que[tail-1], que[tail-2])*get_down(v, que[tail-1]))
        {
            --tail;
            save.push_back(que[tail]);
        }
        que[tail++]=v;
        dfs2(v, u);
        --tail;
        for(int j=0;j<save.size();++j)
            que[tail++]=save[j];
        head=save_head;
    }
}

int main()
{
    LL T_T;
    scanf("%lld", &T_T);
    while(T_T--)
    {
        scanf("%lld%lld", &V, &P);
        init();
        for(LL i=1;i<V;++i)
        {
            LL u, v, c;
            scanf("%lld%lld%lld", &u, &v, &c);
            G[u].push_back(make_pair(v, c));
            G[v].push_back(make_pair(u, c));
        }
        dfs1(1, -1);
        dp[1]=0;
        que[tail++]=1;
        dfs2(1, -1);
        printf("%lld\n", ans-P);
    }

    return 0;
}
阅读更多

没有更多推荐了,返回首页