zoukankan      html  css  js  c++  java
  • codeforces 671D

    首先O(n2)dp很好想

    f[i][j]表示i子树内的所有边都被覆盖且i~j的路径也都被覆盖的最小花费。

    考虑去掉无用的状态,其实真正用到的就是每一条链。

    去掉第二维,f[i]表示i子树内的边都被覆盖且父向边也被覆盖的最小花费。

    那么怎么转移呢?

    f[i]可以是任意一条包含i和fa[i]的链转移而来,

    首先要选这条链,还要加上这条链下端点到i所有其他儿子的f值,这样复杂度好像依旧很高

    再优化,这不就是线段树取一个min吗?

    那么我们现在要做的就是在每一个点上,在对应的一些链中取一个min

    对于每条链,它是在它的下端点之上开始做出贡献的,

    所以每个点控制的区间要是它的子树中所有向上连的边

    当我们搞点x时,首先要算出他所有儿子的f值加和sum.然后要将以x为下端点的链的值更新为sum+c[i],还要将所有以x为上端点的链赋值inf,还要对其所有儿子的控制的链都加上sum-f[son],最后对于他控制的所有链取一个min就好了.

    代码

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define N 300005
     7 #define inf 1000000000000000ll
     8 #define LL long long
     9 using namespace std;
    10 int n,m,c[N];
    11 int e=1,head[N],out[N],in[N];
    12 struct edge{int v,next;}ed[4*N];
    13 void add(int u,int v,int *h){
    14     ed[e]=(edge){v,h[u]};
    15     h[u]=e++;
    16 }
    17 int L[N],R[N],tot,d[N];
    18 void dfs(int x,int fa){
    19     L[x]=tot+1;
    20     for(int i=in[x];i;i=ed[i].next)
    21         d[ed[i].v]=++tot;
    22     for(int i=head[x];i;i=ed[i].next)
    23         if(ed[i].v!=fa)dfs(ed[i].v,x);
    24     R[x]=tot;
    25 }
    26 LL f[N];
    27 LL minn[4*N],lazy[4*N];
    28 void update(int rt,int l,int r,int x,LL y){
    29     if(l==r){minn[rt]=y;return ;}
    30     int mid=(l+r)>>1;
    31     if(x<=mid)update(rt<<1,l,mid,x,y);
    32     else update(rt<<1|1,mid+1,r,x,y);
    33     minn[rt]=min(min(minn[rt<<1],minn[rt<<1|1])+lazy[rt],inf);
    34 }
    35 void add(int rt,int l,int r,int x,int y,LL z){
    36     if(x<=l&&r<=y){lazy[rt]+=z;minn[rt]+=z;return ;}
    37     int mid=(l+r)>>1;
    38     if(x<=mid) add(rt<<1,l,mid,x,y,z);
    39     if(y>mid) add(rt<<1|1,mid+1,r,x,y,z);
    40     minn[rt]=min(min(minn[rt<<1],minn[rt<<1|1])+lazy[rt],inf);
    41 }
    42 LL query(int rt,int l,int r,int x,int y){    
    43     if(x<=l&&r<=y) return minn[rt];
    44     LL ans=inf;
    45     int mid=(l+r)>>1;
    46     if(x<=mid)ans=min(ans,query(rt<<1,l,mid,x,y));
    47     if(y>mid) ans=min(ans,query(rt<<1|1,mid+1,r,x,y));
    48     return min(ans+lazy[rt],inf);
    49 }
    50 void solve(int x,int fa){
    51     LL ans=0;
    52     for(int i=head[x];i;i=ed[i].next){
    53         if(ed[i].v==fa)continue;
    54         solve(ed[i].v,x);
    55         ans=min(f[ed[i].v]+ans,inf);
    56     }
    57     if(x==1){f[1]=ans;return;}
    58     for(int i=in[x];i;i=ed[i].next)
    59         update(1,1,m,d[ed[i].v],ans+c[ed[i].v]);
    60     for(int i=out[x];i;i=ed[i].next)
    61         update(1,1,m,d[ed[i].v],inf);
    62     for(int i=head[x];i;i=ed[i].next){
    63         if(ed[i].v==fa)continue;
    64         add(1,1,m,L[ed[i].v],R[ed[i].v],ans-f[ed[i].v]);
    65     }
    66     f[x]=query(1,1,m,L[x],R[x]);
    67 }
    68 
    69 int main(){
    70     scanf("%d%d",&n,&m);
    71     for(int i=1,u,v;i<n;i++){
    72         scanf("%d%d",&u,&v);
    73         add(u,v,head);
    74         add(v,u,head);
    75     }
    76     for(int i=1,u,v;i<=m;i++){
    77         scanf("%d%d%d",&u,&v,&c[i]);
    78         add(u,i,in);
    79         add(v,i,out);
    80     }
    81     dfs(1,0);
    82     memset(minn,0x15f,sizeof minn);
    83     memset(lazy,0,sizeof lazy);
    84     solve(1,0);
    85     if(f[1]>=inf)printf("-1
    ");
    86     else printf("%lld
    ",f[1]);
    87     return 0;
    88 }
    youmu
  • 相关阅读:
    linux如何编译安装新内核支持NTFS文件系统?(以redhat7.2x64为例)
    RAID磁盘阵列的搭建(以raid0、raid1、raid5、raid10为例)
    linux专题一之文件归档和压缩(tar、file、zip)
    linux专题一之文件管理(目录结构、创建、查看、删除、移动)
    CENTOS6.6上搭建单实例ORACLE12C
    oracle12c各个版本对其需要的依赖包及系统参数的修改
    mysql cp复制和mysqldump备份测试
    mysql之mysql_config_editor
    CENTOS6.6下redis3.2集群搭建
    CENTOS6.6 下mysql MHA架构搭建
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/7750414.html
Copyright © 2011-2022 走看看