zoukankan      html  css  js  c++  java
  • bzoj3677: [Apio2014]连珠线

    Description

    在列奥纳多·达·芬奇时期,有一个流行的童年游戏,叫做“连珠线”。不出所料,玩这个游戏只需要珠子和线,珠子从1到礼编号,线分为红色和蓝色。游戏 
    开始时,只有1个珠子,而接下来新的珠子只能通过线由以下两种方式被加入: 
    1.Append(w,杪):-个新的珠子w和一个已有的珠子杪连接,连接使用红线。 
    2.Insert(w,u,v):-个新的珠子w加入到一对通过红线连接的珠子(u,杪) 
    之间,并将红线改成蓝线。也就是将原来u连到1的红线变为u连到w的蓝线与W连到V的蓝线。 
    无论红线还是蓝线,每条线都有一个长度。而在游戏的最后,将得到游戏的 
    最后得分:所有蓝线的长度总和。 
    现在有一个这个游戏的最终结构:你将获取到所有珠子之间的连接情况和所 
    有连线的长度,但是你并不知道每条线的颜色是什么。 
    你现在需要找到这个结构下的最大得分,也就是说:你需要给每条线一个颜 
    色f红色或蓝色),使得这种连线的配色方案是可以通过上述提到的两种连线方式 
    操作得到的,并且游戏得分最大。在本题中你只需要输出最大的得分即可。 

    Input

     
    第一行是一个正整数n,表示珠子的个数,珠子编号为1刭n。 
    接下来n-l行,每行三个正整数ai,bi(l≤ai10000),表示有一条长度为ci的线连接了珠子ai和珠子bi。 

    Output

    输出一个整数,为游戏的最大得分。 

    Sample Input

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

    Sample Output

    60



    HINT

    数据范围满足1≤n≤200000。 

    题解:

    假如确定了根,再通过若干操作得到这棵树,那么对于insert(w,u,v)操作,u,w,v必然为祖父节点-父节点-子节点的形式

    然后可以O(n)的枚举根,设 f[i][0/1] 表示以i为根的子树,i是否为中转点的情况下,子树蓝边的最大总和是多少

    这个可以O(1)的从儿子转移过来,所以dp的复杂度为O(n),但总复杂度为O(n2

    我们可以在状态里多加一个0/1,即设 f[i][0/1][0/1] 表示以i为根的子树,以i的为子树里除去i以外是否有根节点,i是否为中转点的情况下,子树蓝边的最大总和是多少

    当以i的为子树里除去i以外没有根节点,和前面的转移一样

    否则,就会多一种转移,设根节点在j,就是可以有insert(i,j,x),其中x是i的另一个子节点

    code:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 char ch;
     8 bool ok;
     9 void read(int &x){
    10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    12     if (ok) x=-x;
    13 }
    14 const int maxn=200005;
    15 const int maxm=maxn*2;
    16 const int inf=2147483647;
    17 int n,a,b,c;
    18 int f[maxn][2][2];
    19 struct Graph{
    20     int tot,now[maxn],son[maxm],pre[maxm],val[maxm];
    21     int premax[maxn],sufmax[maxn],g[maxn];
    22     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    23     void add(int a,int b,int c){put(a,b,c),put(b,a,c);}
    24     void dfs(int u,int fa){
    25         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (v!=fa) dfs(v,u);
    26         int cnt=0,sum=0; premax[0]=sufmax[0]=-inf;
    27         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (v!=fa)
    28             g[v]=max(f[v][0][0],f[v][0][1]+val[p]),sum+=g[v],++cnt,premax[cnt]=sufmax[cnt]=f[v][0][0]+val[p]-g[v];
    29         premax[cnt+1]=sufmax[cnt+1]=-inf;
    30         for (int i=1;i<=cnt;i++) premax[i]=max(premax[i],premax[i-1]);
    31         for (int i=cnt;i>=1;i--) sufmax[i]=max(sufmax[i],sufmax[i+1]);
    32         f[u][0][0]=sum,f[u][0][1]=cnt?f[u][0][0]+premax[cnt]:-inf,f[u][1][1]=-inf;
    33         for (int p=now[u],v=son[p],i=0;p;p=pre[p],v=son[p]) if (v!=fa){i++;
    34             int res=max(premax[i-1],sufmax[i+1]),tmp=sum-g[v];
    35             f[u][1][0]=max(f[u][1][0],max(f[v][1][1]+val[p]+tmp,max(f[v][0][0],f[v][1][0])+tmp+max(val[p]+res,0)));
    36             f[u][1][1]=max(f[u][1][1],max(f[v][0][0],f[v][1][0])+val[p]+tmp);
    37         }
    38     }
    39 }G;
    40 int main(){
    41     read(n);
    42     for (int i=1;i<n;i++) read(a),read(b),read(c),G.add(a,b,c);
    43     G.dfs(1,0);
    44     printf("%d
    ",max(f[1][1][0],f[1][0][0]));
    45     return 0;
    46 }
  • 相关阅读:
    把影响集中到一个点
    How to avoid Over-fitting using Regularization?
    适定性问题
    Numerical Differentiation 数值微分
    What Every Computer Scientist Should Know About Floating-Point Arithmetic
    Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
    What is the difference between iterations and epochs in Convolution neural networks?
    Every norm is a convex function
    Moore-Penrose Matrix Inverse 摩尔-彭若斯广义逆 埃尔米特矩阵 Hermitian matrix
    perl 类里的函数调用其他类的函数
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5434054.html
Copyright © 2011-2022 走看看