zoukankan      html  css  js  c++  java
  • 【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;
    }

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

  • 相关阅读:
    1014 Waiting in Line (30)(30 point(s))
    1013 Battle Over Cities (25)(25 point(s))
    1012 The Best Rank (25)(25 point(s))
    1011 World Cup Betting (20)(20 point(s))
    1010 Radix (25)(25 point(s))
    1009 Product of Polynomials (25)(25 point(s))
    1008 Elevator (20)(20 point(s))
    1007 Maximum Subsequence Sum (25)(25 point(s))
    1006 Sign In and Sign Out (25)(25 point(s))
    1005 Spell It Right (20)(20 point(s))
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5514784.html
Copyright © 2011-2022 走看看