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

Posted DaD3zZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ-1912patrol巡逻 树的直径 + 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\n",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\n",ans);
    return 0;
}

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

以上是关于BZOJ-1912patrol巡逻 树的直径 + DFS(树形DP)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1912 Apio2010—patrol 巡逻

BZOJ1912 [Apio2010]patrol 巡逻

bzoj 1912: [Apio2010]patrol 巡逻不是dp是枚举+堆

BZOJ 1912:[Apio2010]patrol 巡逻(树直径)

BZOJ1912 [Apio2010]patrol 巡逻

bzoj1912Apio2010patrol 巡逻