码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-05-21 15:47:56      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

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-1912】patrol巡逻 树的直径 + DFS(树形DP)

标签:

原文地址:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5514784.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!