[树形DP]JZOJ 5906 传送门

Description

            8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪。但GLaDOS想把传送枪据为己有,于是把Normalgod扔进了一间实验室。这间实验室是一棵有n个节点的树。现在Normalgod在一号节点,出口也在一号节点,但为了打开它,必须经过每一个节点按下每个节点的开关,出口才能打开。GLaDOS为了杀死Normalgod,开始在实验室里释放毒气,因此Normalgod必须尽快逃出这间实验室。
            当然,Normalgod手中的传送枪是可以使用的。传送枪可以发射出两个颜色不同的传送门。Normalgod可以从其中一个传送到另一个。尽管传送枪可以在视野范围内的任何一个经过特殊处理的表面打开一扇传送门,但这间实验室的设计使得Normalgod只能在他所处的房间内打开一个传送门。 在已经存在了一个同颜色的传送门时,打开新的传送门会使与它同颜色的旧门消失。传送和打开传送门所需时间为0。
             显然,利用传送枪会让Normalgod更快解决谜题,可Normalgod死在了按下最后一个按钮的路上。尽管如此,GLaDOS还是很想知道到底Normalgod最快能用多久逃出去,这对她的实验室设计方法论有重要的指导作用。作为GLaDOS的算法模块,你要完成这个任务。本题时限为2000ms
 

Input

第一行一个整数n。之后n-1行,每行三个整数ui,vi,ai ,表示有一条从ui 连向vi ,花费时间为ai 的通道。

Output

一行一个数T,表示最小的脱逃时间。
 

Sample Input

5
1 2 2
2 3 3
2 4 5
1 5 1
 

Sample Output

13

样例说明
1--> open1--> 5--> open2--> use(1)--> 2--> 3--> open2--> use(1)--> 2--> 4--> open2--> use(1)--> exit
 

Data Constraint

分析

我们知道,一条边至少被经过1次

第二,传送门肯定是从下往上传送的

如果设f[i][0/1]表示走完了以i为根的子树在子树内用/没用传送门的时间,f[i][0]显而易见就等于∑f[son][0]+w[i to son]*2

然后f[i][1]则要额外考虑一下,首先对于不是在i处使用传送门的情况:

f[i][1]+=f[son][1]+w[i to son]*2

在i处使用传送门的情况:

f[i][1]+=f[son][0]+w[i to son]-lengthofline[son]

最后那个意思是以son为起点的最长链的长度,这是显然的,因为使用传送门是可以减少回来的时间

然后综合一下:

f[i][1]+=min(1,2)

而且为了时间最少,答案一定是使用过传送门的,所以ans=f[root][1]

 

#include <iostream> 
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1e6+10;
struct Edge {
    int u,v,nx;
    ll w;
}g[2*N];
int cnt,list[N];
ll f[N][2],l[N];
int n;

void Add(int u,int v,ll w) {
    g[++cnt].u=u;g[cnt].v=v;g[cnt].w=w;g[cnt].nx=list[u];list[u]=cnt;
}

void Dfs(int u,int fa) {
    for (int i=list[u];i;i=g[i].nx)
        if (g[i].v!=fa) {
            Dfs(g[i].v,u);
            l[u]=max(l[u],l[g[i].v]+g[i].w);
            f[u][0]+=f[g[i].v][0]+g[i].w*2;
            f[u][1]+=min(f[g[i].v][1]+g[i].w*2,f[g[i].v][0]+g[i].w-l[g[i].v]);
        }
}

int main() {
    freopen("portal.in","r",stdin);
    freopen("portal.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<n;i++) {
        int u,v;ll w;
        scanf("%d%d%lld",&u,&v,&w);
        Add(u,v,w);Add(v,u,w);
    }
    Dfs(1,-1);
    printf("%lld",f[1][1]);
    fclose(stdin);fclose(stdout);
}
View Code

 

posted @ 2018-10-16 07:27  Vagari  阅读(173)  评论(0编辑  收藏  举报