zoukankan      html  css  js  c++  java
  • BZOJ3743: [Coci2014]Kamp

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3743

    一颗树n个点,n-1条边,经过每条边都要花费一定的时间,任意两个点都是联通的。
    有K个人(分布在K个不同的点)要集中到一个点举行聚会。
    聚会结束后需要一辆车从举行聚会的这点出发,把这K个人分别送回去。
    请你回答,对于i=1~n,如果在第i个点举行聚会,司机最少需要多少时间把K个人都送回家。
    K <= N <= 500000
    1 <= x,y <= N, 1 <= z <= 1000000
    题解:刚开始看见,卧槽这不是奶牛大集合吗,怎么出这种水题,两次DFS搞定。
             下午来了打完代码发现居然是一辆车送多个奶牛,然后想到了up和down,然后又开始写。
              写完发现车可以停在任意一个点,那就是由i点出发到达有奶牛的点的最长链哦,好像也是两次DP?保留一个最优值和次优值。然后写完就A了。。。
             需要注意一点,就是只能用子节点的最优值去更新父节点的值,而不能用次优值,因为这可能导致父节点的最优值和次优值都是该子树内的。。。
             貌似NOIP考这种题还算良心。。。
    代码:
      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 500000+5
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 struct edge{int go,next;ll w;}e[2*maxn];
     61 int n,m,tot,s[maxn],head[maxn];
     62 ll f[maxn],g[maxn],z[maxn][2];
     63 bool v[maxn],a[maxn];
     64 inline void insert(int x,int y,int z)
     65 {
     66     e[++tot]=edge{y,head[x],z};head[x]=tot;
     67     e[++tot]=edge{x,head[y],z};head[y]=tot;
     68 }
     69 inline void down(int x)
     70 {
     71     v[x]=1;s[x]=a[x];
     72     for(int i=head[x],y;i;i=e[i].next)
     73         if(!v[y=e[i].go])
     74         {
     75             down(y);
     76             s[x]+=s[y];
     77             if(s[y])g[x]+=g[y]+e[i].w*2;
     78         }
     79     v[x]=0;    
     80 }
     81 inline void up(int x)
     82 {
     83     v[x]=1;
     84     for(int i=head[x],y;i;i=e[i].next)
     85         if(!v[y=e[i].go])
     86         {
     87             if(s[y]!=m)
     88             {
     89                 if(s[y])f[y]=f[x]+g[x]-g[y];else f[y]=f[x]+g[x]-g[y]+2*e[i].w;
     90             }
     91             up(y);
     92         }
     93     v[x]=0;
     94 }
     95 inline void update(int y,int x)
     96 {
     97     if(y>z[x][0]){z[x][1]=z[x][0];z[x][0]=y;}
     98     else if(y>z[x][1])z[x][1]=y;
     99 }
    100 inline void dp1(int x)
    101 {
    102     v[x]=1;
    103     for(int i=head[x],y;i;i=e[i].next)
    104     if(!v[y=e[i].go])
    105     {
    106         dp1(y);
    107         if(s[y])update(z[y][0]+e[i].w,x);//update(z[y][1]+e[i].w,x);
    108     }
    109     v[x]=0;
    110 }
    111 inline void dp2(int x)
    112 {
    113     v[x]=1;
    114     for(int i=head[x],y;i;i=e[i].next)
    115     if(!v[y=e[i].go])
    116     {
    117         if(z[x][0]==z[y][0]+e[i].w)update(z[x][1]+e[i].w,y);
    118         else update(z[x][0]+e[i].w,y);
    119         dp2(y);
    120     }
    121     v[x]=0;
    122 }
    123 
    124 int main()
    125 
    126 {
    127 
    128     freopen("input.txt","r",stdin);
    129 
    130     freopen("output.txt","w",stdout);
    131 
    132     n=read();m=read();
    133     for1(i,n-1){int x=read(),y=read();insert(x,y,read());}
    134     for1(i,m)a[read()]=1;
    135     down(1);
    136     up(1);
    137     dp1(1);
    138     dp2(1);
    139     //for1(i,n)printf("%d %d %d %d
    ",i,f[i],g[i],z[i][0]);
    140     for1(i,n)printf("%lld
    ",f[i]+g[i]-z[i][0]);
    141 
    142     return 0;
    143 
    144 }
    View Code

     UPD:上面写的求从一个点出发到奶牛点的最长距离写萎了。。。

     正确的姿势应该是z[x][0/1]表示x向下的最长和次长,然后d[x]表示先向上一步的最长链。

    这样:

    inline void dp2(int x)
    {
        v[x]=1;
        for(int i=head[x],y;i;i=e[i].next)
        if(!v[y=e[i].go])
        {
            d[y]=max(d[y],d[x]+e[i].w);
            if(z[x][0]==z[y][0]+e[i].w)d[y]=max(d[y],z[x][1]+e[i].w);
            else d[y]=max(d[y],z[x][0]+e[i].w);
            dp2(y);
        }
        v[x]=0;
    }

    然后就对了。。。233不知道原来怎么A的。。。

    代码:

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 500000+5
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 struct edge{int go,next;ll w;}e[2*maxn];
     61 int n,m,tot,s[maxn],head[maxn];
     62 ll f[maxn],g[maxn],z[maxn][2],d[maxn];
     63 bool v[maxn],a[maxn];
     64 inline void insert(int x,int y,int z)
     65 {
     66     e[++tot]=edge{y,head[x],z};head[x]=tot;
     67     e[++tot]=edge{x,head[y],z};head[y]=tot;
     68 }
     69 inline void down(int x)
     70 {
     71     v[x]=1;s[x]=a[x];
     72     for(int i=head[x],y;i;i=e[i].next)
     73         if(!v[y=e[i].go])
     74         {
     75             down(y);
     76             s[x]+=s[y];
     77             if(s[y])g[x]+=g[y]+e[i].w*2;
     78         }
     79     v[x]=0;    
     80 }
     81 inline void up(int x)
     82 {
     83     v[x]=1;
     84     for(int i=head[x],y;i;i=e[i].next)
     85         if(!v[y=e[i].go])
     86         {
     87             if(s[y]!=m)
     88             {
     89                 if(s[y])f[y]=f[x]+g[x]-g[y];else f[y]=f[x]+g[x]-g[y]+2*e[i].w;
     90             }
     91             up(y);
     92         }
     93     v[x]=0;
     94 }
     95 inline void update(int y,int x)
     96 {
     97     if(y>z[x][0]){z[x][1]=z[x][0];z[x][0]=y;}
     98     else if(y>z[x][1])z[x][1]=y;
     99 }
    100 inline void dp1(int x)
    101 {
    102     v[x]=1;
    103     for(int i=head[x],y;i;i=e[i].next)
    104     if(!v[y=e[i].go])
    105     {
    106         dp1(y);
    107         if(s[y])update(z[y][0]+e[i].w,x);//update(z[y][1]+e[i].w,x);
    108     }
    109     v[x]=0;
    110 }
    111 inline void dp2(int x)
    112 {
    113     v[x]=1;
    114     for(int i=head[x],y;i;i=e[i].next)
    115     if(!v[y=e[i].go])
    116     {
    117         d[y]=max(d[y],d[x]+e[i].w);
    118         if(z[x][0]==z[y][0]+e[i].w)d[y]=max(d[y],z[x][1]+e[i].w);
    119         else d[y]=max(d[y],z[x][0]+e[i].w);
    120         dp2(y);
    121     }
    122     v[x]=0;
    123 }
    124 
    125 int main()
    126 
    127 {
    128 
    129     freopen("input.txt","r",stdin);
    130 
    131     freopen("output.txt","w",stdout);
    132 
    133     n=read();m=read();
    134     for1(i,n-1){int x=read(),y=read();insert(x,y,read());}
    135     for1(i,m)a[read()]=1;
    136     down(1);
    137     up(1);
    138     dp1(1);
    139     dp2(1);
    140     //for1(i,n)printf("%d %d %d %d
    ",i,f[i],g[i],z[i][0]);
    141     for1(i,n)printf("%lld
    ",f[i]+g[i]-max(d[i],z[i][0]));
    142 
    143     return 0;
    144 
    145 }
    View Code
  • 相关阅读:
    Snort 2.9.4.0 发布,入侵检测系统
    Tails 0.15 发布,基于Debian的Linux发行
    httpkit 1.2 发布
    cmogstored 0.9.0 发布,mogstored 的 C 实现
    JSwat 2012.1 发布,Java 调试工具
    诺基亚 Lumia 920T 今日发布 处理器升级
    如何在你的网站中嵌入 RunJS 的代码 (gist)?
    Linux 上的 Darwin/OS X 仿真器 Darling
    Zarafa 7.0.11/7.1.2 发布
    Silverlight实例教程 – Datagrid,Dataform数据验证和ValidationSummary
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4092810.html
Copyright © 2011-2022 走看看