zoukankan      html  css  js  c++  java
  • 【BZOJ】【1912】【APIO2010】patrol巡逻

    树形DP


      说是树形DP,其实就是求树的最长链嘛……

      K=1的时候明显是将树的最长链的两端连起来最优。

      但是K=2的时候怎么搞?

      考虑第一次找完树的最长链以后的影响:第一次找过的边如果第二次再走,对答案的贡献会变成-1,因为两次都选这一段的话,反而会使得这一段不得不走两次(如果只被选一次的话就可以只走一次),所以就将第一次找出的树的最长链上的边权值都改为-1。这个操作可以用链表实现(类比一下最小费用最大流的spfa实现!)

      题解:http://blog.csdn.net/qpswwww/article/details/43935861

     1 /**************************************************************
     2     Problem: 1912
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:580 ms
     7     Memory:5752 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1912
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 #define CC(a,b) memset(a,b,sizeof(a))
    22 using namespace std;
    23 inline int getint(){
    24     int v=0,sign=1; char ch=getchar();
    25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    27     return v*sign;
    28 }
    29 const int N=1e5+10,INF=~0u>>2;
    30 typedef long long LL;
    31 /******************tamplate*********************/
    32 int head[N],to[N<<1],next[N<<1],len[N<<1],cnt=1;
    33 void add(int x,int y){
    34     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=1;
    35     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; len[cnt]=1;
    36 }
    37 int n,K;
    38 int D,S,son1[N],son2[N];
    39 int dfs(int x,int fa){
    40     int m1=0,m2=0;
    41     for(int i=head[x];i;i=next[i])
    42         if (to[i]!=fa){
    43             int nowh=dfs(to[i],x)+len[i];
    44             if (nowh>m1){m2=m1;m1=nowh;son2[x]=son1[x];son1[x]=i;}
    45             else if (nowh>m2){m2=nowh; son2[x]=i;}
    46         }
    47     if (D<m1+m2) D=m1+m2,S=x;
    48     return m1;
    49 }
    50 int main(){
    51 #ifndef ONLINE_JUDGE
    52     freopen("1912.in","r",stdin);
    53     freopen("1912.out","w",stdout);
    54 #endif
    55     n=getint(); K=getint();
    56     F(i,2,n){
    57         int x=getint(),y=getint();
    58         add(x,y);
    59     }
    60     int ans=(n-1)<<1;
    61     D=0;
    62     CC(son1,-1);
    63     CC(son2,-1);
    64     dfs(1,-1);
    65     ans-=D-1;
    66     if (K>1){
    67         D=0;
    68         for(int i=son1[S];i!=-1;i=son1[to[i]]) len[i]=len[i^1]=-1;
    69         for(int i=son2[S];i!=-1;i=son1[to[i]]) len[i]=len[i^1]=-1;
    70         CC(son1,-1);
    71         CC(son2,-1);
    72         dfs(1,-1);
    73         ans-=D-1;
    74     }
    75     printf("%d
    ",ans);
    76     return 0;
    77 }
    78 
    View Code

    1912: [Apio2010]patrol 巡逻

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 642  Solved: 362
    [Submit][Status][Discuss]

    Description

    Input

    第一行包含两个整数 n, K(1 ≤ K ≤ 2)。接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n)。

    Output

    输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离。

    Sample Input

    8 1
    1 2
    3 1
    3 4
    5 3
    7 5
    8 5
    5 6

    Sample Output

    11

    HINT

    10%的数据中,n ≤ 1000, K = 1;
    30%的数据中,K = 1;
    80%的数据中,每个村庄相邻的村庄数不超过 25;
    90%的数据中,每个村庄相邻的村庄数不超过 150;
    100%的数据中,3 ≤ n ≤ 100,000, 1 ≤ K ≤ 2。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    求10个随机数的最大值、最小值、和、平均值
    设计并编写代码自动格斗类游戏
    用while实现阶乘
    安卓第三次作业
    第二次作业
    第一次作业
    第四次作业
    dialog
    用画图的方法理解原型对象和原型链,事半功倍今晚不加班
    【学习笔记】浅析Promise函数
  • 原文地址:https://www.cnblogs.com/Tunix/p/4467694.html
Copyright © 2011-2022 走看看