• 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
  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5595166.html
Copyright © 2020-2023  润新知