• 【BZOJ-1912】patrol巡逻 树的直径 + DFS(树形DP)


    1912: [Apio2010]patrol 巡逻

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 1034  Solved: 562
    [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

    Solution

    发现加边实际上就是形成环,使得一条路径可以直接绕回来,不用原路返回

    那么K==1的时候,边一定用来连最长的路径(树的直径)那么DFS出即可

    K==2的时候同理,不过需要次短,同样DFS,对第一次DFS求得的路径做些修改,置成-1就可以

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    #define maxn 100010
    int n,k,ans,zj,s;
    struct EdgeNode{int next,to,len;}edge[maxn<<1];
    int head[maxn],cnt=1;int road[maxn]={0},croad[maxn]={0};
    void add(int u,int v,int w)
    {
        cnt++;
        edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].len=w;
    }
    void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);}
    int DFS(int now,int fa)
    {
        int maxd=0,cmaxd=0;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=fa)
                {
                    int len=DFS(edge[i].to,now)+edge[i].len; 
                    if (len>maxd) cmaxd=maxd,maxd=len,croad[now]=road[now],road[now]=i;            
                    else if (len>cmaxd) cmaxd=len,croad[now]=i;
                }
        if (maxd+cmaxd>zj) zj=maxd+cmaxd,s=now;
    //    printf("%d %d %d %d
    ",now,fa,maxd,cmaxd);
        return maxd;
    }
    int main()
    {
        n=read(); k=read();
        for (int u,v,i=1; i<=n-1; i++) u=read(),v=read(),insert(u,v,1);
        DFS(1,0); ans=2*(n-1)-zj+1;
        if (k==2)
            {
                for (int i=road[s]; i; i=road[edge[i].to]) edge[i].len=edge[i^1].len=-1;
                for (int i=croad[s]; i; i=road[edge[i].to]) edge[i].len=edge[i^1].len=-1;
                zj=0; DFS(1,0); ans=ans-zj+1;
            }
        printf("%d
    ",ans);
        return 0;
    }

    自己的代码写炸了,不知为何..

  • 相关阅读:
    linux
    java对象结构
    jvm之java类加载机制和类加载器(ClassLoader)的详解
    二进制运算符及补码
    java导出word格式的文件
    rpm命令详解
    word转pdf
    应用缓存
    fullPage.js+Stellar.js+circlr.js
    评分案例
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5514784.html
Copyright © 2020-2023  润新知