JZOJ5906 传送门
Description
8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪。但GLaDOS想把传送枪据为己有,于是把Normalgod扔进了一间实验室。这间实验室是一棵有n个节点的树。现在Normalgod在一号节点,出口也在一号节点,但为了打开它,必须经过每一个节点按下每个节点的开关,出口才能打开。GLaDOS为了杀死Normalgod,开始在实验室里释放毒气,因此Normalgod必须尽快逃出这间实验室。
当然,Normalgod手中的传送枪是可以使用的。传送枪可以发射出两个颜色不同的传送门。Normalgod可以从其中一个传送到另一个。尽管传送枪可以在视野范围内的任何一个经过特殊处理的表面打开一扇传送门,但这间实验室的设计使得Normalgod只能在他所处的房间内打开一个传送门。 在已经存在了一个同颜色的传送门时,打开新的传送门会使与它同颜色的旧门消失。传送和打开传送门所需时间为0。
显然,利用传送枪会让Normalgod更快解决谜题,可Normalgod死在了按下最后一个按钮的路上。尽管如此,GLaDOS还是很想知道到底Normalgod最快能用多久逃出去,这对她的实验室设计方法论有重要的指导作用。作为GLaDOS的算法模块,你要完成这个任务。本题时限为2000ms
当然,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
Solution
我们可以采用动态规划来求解 dp[i][0/1]
0表示在i点及i点儿子设传送门所能得到的最大总和
1 表示不在i点及i点儿子设传送门所能得到的最大总和
首先,对于dp[i][1]的情况,一定存在i点的祖先中有传送门,这样才能使结果更优。所以对于他的每一个儿子都能跳回到他的祖先。但实际上只有使一个儿子跳回祖先时,才能保证fa->i的边经过两次。
否则转化为dp[i][0]的情况。则我们要使选的儿子最优。
dp[i][1]=max(dp[vi][1]+wi);
其次,对于dp[i][0]的情况,在每个儿子中设立传送门并不会影响到其他儿子,因为总能从儿子回到i时再在i重设传送门。所以我们就取每个儿子设与不设的最优值之和。
dp[i][0]=max(dp[vi][0],dp[vi][1]+wi);
1 #include <cstdio> 2 #define N 1000007 3 #define LL long long 4 using namespace std; 5 struct arr { 6 long long w; 7 int x,y,next; 8 }; 9 arr edge[N*2]; 10 int ls[N],n; 11 LL f[N][2],ans; 12 bool p[N]; 13 14 LL max(LL x,LL y){ 15 if (x>y) return x; 16 return y; 17 } 18 19 int dfs(int s){ 20 int i=ls[s]; 21 while (i!=0){ 22 int d=edge[i].y; 23 if (p[d]){ 24 p[d]=false; 25 dfs(d); 26 f[s][1]=max(f[s][1],f[d][1]+edge[i].w); 27 f[s][0]+=max(f[d][0],f[d][1]+edge[i].w); 28 } 29 i=edge[i].next; 30 } 31 } 32 33 int add(int x,int y,LL w,int e){ 34 edge[e].x=x; edge[e].y=y; edge[e].w=w; 35 edge[e].next=ls[edge[e].x]; ls[edge[e].x]=e; 36 edge[--e].x=y; edge[e].y=x; edge[e].w=w; 37 edge[e].next=ls[edge[e].x]; ls[edge[e].x]=e; 38 } 39 40 int main() 41 { 42 scanf("%d",&n); 43 ls[1]=1; 44 for (int i=1;i<n;i++){ 45 int x,y; 46 LL w; 47 scanf("%d%d%lld",&x,&y,&w); 48 add(x,y,w,i*2); 49 ans+=w*2; 50 } 51 for (int i=1;i<=n;i++) 52 p[i]=true; 53 p[1]=false; 54 dfs(1); 55 ans-=max(f[1][1],f[1][0]); 56 printf("%lld\n",ans); 57 }