zoukankan      html  css  js  c++  java
  • BZOJ1912[Apio2010]patrol 巡逻

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1912

    题解:嗯,这是一道很好的题。

    转自:http://www.cnblogs.com/iwtwiioi/p/4126284.html

      对于 k==0 的情况: 
      我们发现遍历一棵树最后回到原点,那么对于所有的边,我们都是走过去,再走回来。 
      答案 (n1<<1)

      对于 k==1 的情况 
      设每条边长度为1,然后树上找最长链,然后这条链走过去就不再一步步往回了,直接从链底连一条边去链顶,然后链中间连的那些点,直接走过去再走回来,它们那些边的答案是不变的。 
      答案 (n1<<1)()+1 
      可以证明不能减得更多啦。

      z对于 k==2 的情况 
      设上一次的直径上的边的边长都为-1,因为再走一次会坑,然后树上找最长链。 
      答案 (n1<<1)(1)+1(2)+1 
      可以证明不能减得更多啦。

      我在这里就不贴出证明了,以免给读者养成不自己证明的惰性(其实是我这两天惰性有点大2333)

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define maxn 100005
     7 #define maxm 200005
     8 int n,k,c;
     9 int ans,sum,mx,tot;
    10 int s1[maxm],s2[maxm];
    11 int now[maxn],pre[maxm],v[maxm],val[maxm];
    12 int read()
    13 {
    14     int x=0; char ch; bool bo=0;
    15     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
    16     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
    17     if (bo) return -x; return x;
    18 }
    19 void ins(int a,int b,int c)
    20 {
    21     ++tot; pre[tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c;
    22 }
    23 int dfs(int x,int fa)
    24 {
    25     int mx1=0,mx2=0;
    26     for (int p=now[x]; p; p=pre[p])
    27     {
    28         int son=v[p];
    29         if (son==fa) continue;
    30         int vv=val[p]+dfs(son,x);
    31         if (vv>mx1) mx2=mx1,mx1=vv,s2[x]=s1[x],s1[x]=p;
    32         else if (vv>mx2) mx2=vv,s2[x]=p;
    33      }
    34      if (mx1+mx2>sum) sum=mx1+mx2,mx=x;
    35      return mx1;
    36 }
    37 int main()
    38 {
    39     n=read(); k=read(); int c=1;
    40     for (int i=1; i<n; i++)
    41     {
    42         int u=read(),v=read(),val=1;
    43         ins(u,v,val); ins(v,u,val);
    44         ans+=2*val;
    45     }
    46     dfs(1,0);
    47     ans-=sum-1;
    48     if (k==2)
    49     {
    50         for (int p=s1[mx]; p; p=s1[v[p]]) val[p]=-1*val[p];
    51         for (int p=s2[mx]; p; p=s1[v[p]]) val[p]=-1*val[p];
    52         sum=0;
    53         dfs(1,0); ans-=sum-1;
    54     }
    55     printf("%d
    ",ans);
    56 }
    View Code

    注:可以想想k不等于2,而是大于2怎么做,因为某次noi模拟赛就是这道题的加强版【这道题就不给题面了,你懂得!】,k的大小不限,于是怎么做呢???有两种做法:tree dp,还有就是这个写法,但是要改一些东东,自己可以想想,自己也写写,然后可以用我程序对拍。

    代码如下:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define maxn 2005
     7 #define maxm 4005
     8 using namespace std;
     9 int n,k,c;
    10 int ans,sum,mx,tot;
    11 int s1[maxm],s2[maxm];
    12 int now[maxn],pre[maxm],v[maxm],val[maxm];
    13 bool bo[maxm];
    14 int read()
    15 {
    16     int x=0; char ch; bool bo=0;
    17     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
    18     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
    19     if (bo) return -x; return x;
    20 }
    21 void ins(int a,int b,int c)
    22 {
    23     ++tot; pre[tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c;
    24 }
    25 int dfs(int x,int fa)
    26 {
    27     int mx1=0,mx2=0;
    28     for (int p=now[x]; p; p=pre[p])
    29     {
    30         int son=v[p];
    31         if (son==fa) continue;
    32         int vv=val[p]+dfs(son,x);
    33         if (vv>mx1) mx2=mx1,mx1=vv,s2[x]=s1[x],s1[x]=p;
    34         else if (vv>mx2) mx2=vv,s2[x]=p;
    35      }
    36      if (mx1+mx2>sum) sum=mx1+mx2,mx=x;
    37      return mx1;
    38 }
    39 void clear()
    40 {
    41     for (int i=1; i<=maxn; i++) now[i]=s1[i]=s2[i]=0;
    42     ans=0; tot=0;
    43 }
    44 int main()
    45 {
    46     //freopen("data.in","r",stdin);
    47     //freopen("wrong.out","w",stdout);
    48     while (scanf("%d
    ",&n)!=EOF)
    49     {
    50         clear();
    51         k=read(); int c=read();
    52         for (int i=1; i<n; i++)
    53         {
    54             int u=read()+1,v=read()+1,val=read();
    55             ins(u,v,val); ins(v,u,val);
    56             ans+=2*val;
    57         }
    58         //cout<<"       "<<ans<<endl;
    59         memset(bo,1,sizeof(bo));
    60         for (int i=1; i<=k; i++)
    61         {
    62             sum=0; mx=0;
    63             for (int j=1; j<=n; j++) s1[j]=s2[j]=0;
    64             dfs(1,0); 
    65             if (sum-c>0)
    66             {
    67                 //cout<<"               "<<sum<<" "<<c<<" "<<mx<<endl;
    68                 ans-=sum-c;
    69                 for (int p=s1[mx]; p; p=s1[v[p]]) val[p]=-1*val[p];
    70                 for (int p=s2[mx]; p; p=s1[v[p]]) val[p]=-1*val[p];
    71             }
    72             //cout<<"     ans   "<<" "<<ans<<endl;
    73         }
    74         printf("%d
    ",ans);
    75     }
    76 }
    77 /*
    78 6 6 4
    79 0 1 9
    80 1 2 10
    81 2 3 2
    82 4 1 9
    83 5 2 8
    84 */
    View Code
  • 相关阅读:
    ansible-乱
    linux-PXE-12
    linux-ntp-10
    linux-selinxu---性能 -8
    linux-系统启动流程-7
    linux-网络管理-6
    linux-文件系统-5
    linux-包管理器-4
    linux-shell脚本基础-2
    linux-history-ps1-1
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5595166.html
Copyright © 2011-2022 走看看