HDU5956 The Elder(树上斜率DP)

来源:互联网 发布:管线三维数据采集 编辑:程序博客网 时间:2024/05/22 10:36

题目:

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.

http://acm.split.hdu.edu.cn/showproblem.php?pid=5956

题意:

蛤题材,就是一颗树上每条边有个权值,每个节点都有新闻要送到根节点就是1节点,运送过程中如果不换青蛙就是走过的所有边权之和的平方,如果换就每次更换要加上P,也就是求“每个节点到根节点这段路径切分成几块之后 [每块的权值和的平方加上(块个数-1)*P] 的最小值”。然后找到所有节点中消耗最大的那个是多少。

思路:

明显是树DP,先推一下转移方程:dp[i] = min{dp[j]+P+(sum[i]-sum[j])^2} 如此明显的斜率优化DP,那么就很简单了只要书上跑DP用斜率优化把O(N^2)优化到O(N)就行了。

斜率优化可以先看看这道题,基本完全一样:http://acm.split.hdu.edu.cn/showproblem.php?pid=3507

然后就是怎么在树上跑,关键是每次搜索完一个儿子的子树之后要把优先队列恢复到原先的状况,然后再搜索下一个儿子,我的写法就是对于每个搜索步骤设置time然后用一个栈储存每次的修改,回溯的时候一直弹出栈中的修改恢复过来直到当前点的time为止。

代码:

//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 112345using namespace std;int n,m,a[N],q[N],head,tail,timee;long long sum[N],dp[N];long long dy(int i){    return dp[i]+sum[i]*sum[i];}long long dx(int j,int k){    return 2*(sum[j]-sum[k]);}long long f(int j,int k){    return ((dy(j)-dy(k)));}vector<int>g[N];vector<int>v[N];struct node{    int pos,num,timee;}tmp;stack<node>st;void dfs(int now,int fa){    int ti=timee++;    int i,j;    while(head<tail && f(q[head+1],q[head])<=sum[now]*dx(q[head+1],q[head]))++head;    dp[now]=dp[q[head]]+(sum[now]-sum[q[head]])*(sum[now]-sum[q[head]])+m;    while(head<tail&&f(now,q[tail])*dx(q[tail],q[tail-1])<=f(q[tail],q[tail-1])*dx(now,q[tail]))    {        tmp.pos=tail;        tmp.num=q[tail];        tmp.timee=ti;        st.push(tmp);        --tail;    }    q[++tail]=now;    int he=head,ta=tail;    for(int i=0;i<g[now].size();i++)        if(fa!=g[now][i])        {            sum[g[now][i]]=sum[now]+v[now][i];            head=he,tail=ta;            while(!st.empty())            {                tmp=st.top();                if(tmp.timee<=ti)break;                q[tmp.pos]=tmp.num;                st.pop();            }            dfs(g[now][i],now);        }}int main(){    int i,j,k,cas,T,t,x,y,z;    scanf("%d",&T);    cas=0;    while(T--)    {        scanf("%d%d",&n,&m);        int i,j;        for(i=1;i<=n;i++)g[i].clear(),v[i].clear();        for(i=1;i<n;i++)        {            scanf("%d%d%d",&x,&y,&z);            g[x].push_back(y);            v[x].push_back(z);            g[y].push_back(x);            v[y].push_back(z);        }        while(!st.empty())st.pop();timee=0;        head=0,tail=-1;        sum[1]=sum[0]=0;        dp[1]=-m;        q[++tail]=1;        int he=head,ta=tail;        for(i=0;i<g[1].size();i++)            {                head=he,tail=ta;                while(!st.empty())                {                    tmp=st.top();                    if(tmp.timee<=0)break;                    q[tmp.pos]=tmp.num;                    st.pop();                }                sum[g[1][i]]=sum[1]+v[1][i];                dfs(g[1][i],1);            }        long long res=0;        for(i=1;i<=n;i++)            res=max(res,dp[i]);        printf("%I64d\n",res);    }    return 0;}


1 0
原创粉丝点击