bzoj1912(树的直径)

BZOJ1912」[Apio2010] patrol 巡逻

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直接求树的直径

k=2时把原来直径权值变为负值求直径,因为形成的两个环可能有重叠,取反后-(-1)变为+1

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

const int maxn=100000+10;
const int nil=0x3f3f3f3f;

struct my{
    int v;
    int next;
    int w;
};

my bian[maxn*2];
queue<int>Q;
int ans;
int p,fa=1,adj[maxn],d[maxn],pre[maxn],dp[maxn],vis[maxn],n,k;;

void myinsert(int u,int v,int w){
     bian[++fa].v=v;
     bian[fa].w=w;
     bian[fa].next=adj[u];
     adj[u]=fa;
}

int bfs(int s){
    memset(d,0x3f,sizeof(d));
    Q.push(s);
    d[s]=0;
    pre[s]=0;
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for (int i=adj[u];i;i=bian[i].next){
            int v=bian[i].v;
            if(d[v]==nil) {
                d[v]=d[u]+1;
                pre[v]=i;
                Q.push(v);
            }
        }
    }
    int x,y;
    for (x=y=1;x<=n;x++) if(d[x]>d[y]) y=x;
    return y;
}

int get(){
    p=bfs(1);
    p=bfs(p);
    return d[p];
}

int dfs(int x){
     vis[x]=true;
     for (int i=adj[x];i;i=bian[i].next){
        int v=bian[i].v;
        if(!vis[v]){
            dfs(v);
            ans=max(ans,dp[x]+dp[v]+bian[i].w);
            dp[x]=max(dp[x],dp[v]+bian[i].w);
        }
     }
     return ans;
}

void change(){
     for (;pre[p];p=bian[pre[p]^1].v) {//可以记录路径,但是一直没搞懂是怎么回事,可能是我太弱吧,记住好了
           // printf("%d %d ",bian[pre[p]].v,bian[pre[p]^1].v);
            bian[pre[p]].w=bian[pre[p]^1].w=-1;
     }
}

int main(){
    int u,v;
    scanf("%d%d",&n,&k);
    for (int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        myinsert(u,v,1);
        myinsert(v,u,1);
    }
    int x=get();
    if(k==1){
        printf("%d
",2*(n-1)-(x-1));
    }
    else {
        change();
        int y=dfs(1);
        printf("%d
",2*n-x-y);
    }
return 0;
}
原文地址:https://www.cnblogs.com/lmjer/p/9355780.html