HDU-5956 The Elder(树型dp+斜率优化)

来源:互联网 发布:人工智能取代人类辩论 编辑:程序博客网 时间:2024/06/09 20:28

The Elder

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


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
36 101 2 42 3 51 4 34 5 35 6 36 301 2 42 3 51 4 34 5 35 6 36 501 2 42 3 51 4 34 5 35 6 3
 

Sample Output
517581
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^2Consequently, the news in the 6-th city requires most time to reach the capital.


题意:有n个节点的树,每个节点都有新闻要送到根节点1,每到一个节点可以选择换人或者不换

①如果选择不换人连续跑距离L,则需要时间L^2

②如果选择换人,那么要等待时间P

问:在每个节点都采取最优的策略时,哪个节点耗时最多

题解:树型DP+斜率优化
根据题意可以知道,每个节点运送新闻时都是沿着自己的父节点走的,记录每个节点u到根节点的距离dir[u],
那么它离自己任意父节点v的距离为dis(u,v)=dir[u]-dir[v]

如果选择在[u,v]这一段不换人,那么花费为dis(u,v)^2
设从节点u到根节点的最优时间为dp[u]
那么dp[u]=min(dp[v]+dis(u,v)^2+P)

显然,如果进行普通的DP求解复杂度为O(N^2),绝对会超时


学过斜率优化的都知道,这个方程是符合斜率优化方程的:
设k为j的父节点,j为i的父节点,设dp[j]+dis(i,j)^2+P<=dp[k]+dis(i,k)^2+P
                            => (dp[j]+dir[j]^2-dp[k]-dir[k]^2)/2(dir[j]-dir[k])<=dir[i]

要注意的一点是,在DFS中,进行了q[t]=u的操作后,在退出函数时,需要将q[t]还原(因为每个节点的子节点可能不止一个)
更更更更加注意的:k=dy/dx!!!!!!!(把dx和dy写反找bug找了一晚上)

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MX = 1e5 + 5;struct Edge{    int v,w,nxt;}E[MX*2];int head[MX],tot,n;void init(){    memset(head,-1,sizeof(head));    tot=0;}void add(int u,int v,int w){    E[tot].v=v;    E[tot].w=w;    E[tot].nxt=head[u];    head[u]=tot++;}//¾àÀëLL dir[MX];bool vis[MX];void init(int n){    for(int i=0;i<=n;i++) dir[i]=vis[i]=0;}void dfs(int u) {    vis[u]=1;    for (int i = head[u]; ~i ; i = E[i].nxt) {        if (vis[E[i].v]) continue;        int v = E[i].v , w = E[i].w;        dir[v] = dir[u] + w;        dfs(v);    }}LL dis(int u,int v){    return abs(dir[u]-dir[v]);}//¶¯Ì¬¹æ»®int q[MX];LL ans,dp[MX],p;LL dy(int j,int k){    return (dp[j]+dir[j]*dir[j])-(dp[k]+dir[k]*dir[k]);}LL dx(int j,int k){    return 2*(dir[j]-dir[k]);}LL DP(int i,int j){    return dp[j]+dis(i,j)*dis(i,j)+p;}void DFS(int u,int fa,int s,int t){    int pre=-1;    if(u!=1){        while(s<t&&dy(q[s+1],q[s])<=dir[u]*dx(q[s+1],q[s])) s++;        dp[u]=min(dp[u],DP(u,q[s]));        while(s<t&&dy(q[t],q[t-1])*dx(u,q[t])>=dy(u,q[t])*dx(q[t],q[t-1])) t--;        pre=q[++t];        q[t]=u;    }    ans=max(ans,dp[u]);    for(int i=head[u];~i;i=E[i].nxt){        int v=E[i].v;        if(v==fa) continue;        DFS(v,u,s,t);    }    if(pre!=-1) q[t]=pre;}int main(){    int T;    //freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&p);        init();        init(n);        for(int i=1;i<n;i++){            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            add(u,v,w);            add(v,u,w);        }        dfs(1);        for(int i=1;i<=n;i++) dp[i]=dir[i]*dir[i];        q[0]=0;ans=0;        DFS(1,0,1,0);        printf("%lld\n",ans);    }    return 0;}


原创粉丝点击