zoukankan      html  css  js  c++  java
  • bzoj 1912 巡逻(树直径)

    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。

    首先对于k=1的数据,yy一下就可以发现要找树的直径,然而对于k=2的点,相当于找两条直径,但是会发现,如果这两条直径重复了会很蛋疼,还是会重复走到,因此我们找完第一个直径后,直径上面的边全部赋值为-1,然后再找第二条直径。
     
     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 int tot,go[200005],first[100005],next[200005];
     7 int op[200005];
     8 int vis[100005],dis[100005],c[200005],from[100005],pre[100005];
     9 int d[100005],n,k,ans,Mx2,val[200005];
    10 void insert(int x,int y,int z){
    11     tot++;
    12     go[tot]=y;
    13     next[tot]=first[x];
    14     first[x]=tot;
    15     val[tot]=z;
    16 }
    17 void add(int x,int y,int z){
    18     insert(x,y,z);op[tot]=tot+1;
    19     insert(y,x,z);op[tot]=tot-1;
    20 }
    21 void bfs(int x){
    22     int h=0,t=1;
    23     for (int i=1;i<=n;i++) pre[i]=from[i]=0;
    24     for (int i=1;i<=n;i++) vis[i]=0,dis[i]=0;
    25     c[1]=x;vis[x]=1;dis[x]=0;
    26     while (h<=t){
    27         h++;
    28         for (int i=first[c[h]];i;i=next[i]){
    29             int pur=go[i];
    30             if (vis[pur]) continue;
    31             pre[pur]=c[h];
    32             from[pur]=i;
    33             vis[pur]=1;c[++t]=pur;dis[pur]=dis[c[h]]+val[i];
    34         }
    35     }
    36 }
    37 void pianfen1(){
    38     bfs(1);
    39     int mx=1;
    40     for (int i=2;i<=n;i++) if (dis[i]>dis[mx]) mx=i;
    41     bfs(mx);
    42     Mx2=1;
    43     for (int i=2;i<=n;i++) if (dis[Mx2]<dis[i]) Mx2=i;
    44     if (k==1) printf("%d
    ",2*(n-1)-dis[Mx2]+1);
    45 }
    46 void dfs(int x){
    47     d[x]=0,vis[x]=1;int mx1=0,mx2=0;
    48     for (int i=first[x];i;i=next[i]){
    49         int pur=go[i];
    50         if (vis[pur]) continue;
    51         dfs(pur);
    52         if (d[pur]+val[i]>mx1) mx2=mx1,mx1=d[pur]+val[i];
    53         else
    54         if (d[pur]+val[i]>mx2) mx2=d[pur]+val[i];
    55     }
    56     if (mx1+mx2>ans) ans=mx1+mx2;
    57     d[x]=mx1;
    58 }
    59 int main(){
    60     scanf("%d%d",&n,&k);
    61     for (int i=1;i<n;i++){
    62         int x,y;
    63         scanf("%d%d",&x,&y);
    64         add(x,y,1);
    65     }
    66     pianfen1();
    67     int cnt=2*(n-1)-dis[Mx2]+1;
    68     if (k==1) return 0;
    69     for (int i=1;i<=n;i++) vis[i]=0,d[i]=0x3f3f3f3f;
    70     for (int i=Mx2;i!=0;i=pre[i]) val[from[i]]=-1,val[op[from[i]]]=-1;
    71     ans=0;
    72     dfs(1);
    73     
    74     printf("%d
    ",cnt-ans+1);
    75 }
  • 相关阅读:
    编程这几天出现的很2的问题!!!
    2020 8 1 每日总结
    2020 8 6 每日总结
    2020 8 7 读后感
    2020 8 4 每日总结
    2020 7 30 每日总结
    2020 8 3 每日总结
    2020 8 8 每日总结
    2020 8 2 每周总结
    2020 8 5 每日总结
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5535821.html
Copyright © 2011-2022 走看看