【JZOJ 3861】【JSOI2014】支线剧情2

来源:互联网 发布:通州梨园淘宝城拆了吗 编辑:程序博客网 时间:2024/06/02 11:20

Description

这里写图片描述

Solution

显然的树形DP,
gx表示以点x根,一次存档也没有,跑完所有子树的时间,
fx表示以x的子树全部跑完所需的时间,可以有存档,也可以没有,(包含从根走下来的时间)
有三种情况,
1. 当前点存档,子树没有存档,
2. 当前点存档,子树只有一个存档,
3. 当前点存档,子树有一个存档,其他的点想存档要从根走下来,

情况1,3比较好做,先考虑,转移显然,每个儿子要转移一个min上来,
情况2在计算完1,3后再单独计算,

复杂度:O(n)

Code

#include <iostream>#include <cstdio>#include <cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)#define efo(i,q) for(int i=A[q];i;i=B[i][0])using namespace std;typedef long long LL;const int N=1e6+500;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n,m;int B[2*N][3],A[N],B0;struct qqww{    int s;}a[N];LL f[N],g[N];void link(int q,int w,int e){    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w,B[B0][2]=e;    B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q,B[B0][2]=e;}int dfsf(int q,int fa){    efo(i,q)if(B[i][1]!=fa)a[q].s+=dfsf(B[i][1],q),g[q]+=g[B[i][1]]+a[B[i][1]].s*B[i][2];    return (a[q].s=max(a[q].s,1));}void dfs(int q,LL e,int fa){    LL t=e;    efo(i,q)if(B[i][1]!=fa)    {        dfs(B[i][1],e+B[i][2],q);        t+=min(g[B[i][1]]+B[i][2]*a[B[i][1]].s,f[B[i][1]]);    }    f[q]=t;    efo(i,q)if(B[i][1]!=fa)    {        LL t1=min(g[B[i][1]]+B[i][2]*a[B[i][1]].s,f[B[i][1]]);        f[q]=min(f[q],t-t1+f[B[i][1]]-e);    }}int main(){    int q,w,e;    read(n);    fo(i,1,n)    {        read(q);        fo(j,1,q)read(w),read(e),link(i,w,e);    }    dfsf(1,0);    dfs(1,0,0);    // fo(i,1,n)printf("%d  %lld %lld\n",i,f[i],g[i]);printf("\n");    printf("%lld\n",f[1]);    return 0;}
0 0
原创粉丝点击