[BZOJ 2657][Zjoi2012]旅游(journey):树的直径

点击这里查看原题

这道题应该把城市看成点,相邻的城市之间连边,这样会形成一棵树,答案即为树的直径。

/*
User:Small
Language:C++
Problem No.:2657
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=2e5+5,mod=5e6;
int n,tot,fir[M],dis[M];
struct edge{
    int v,nex;
}e[M<<1];
void add(int u,int v){
    e[++tot]=(edge){v,fir[u]};
    fir[u]=tot;
}
struct Hash{
    int fir[mod+5],tot,nex[M*3],v[M*3];
    ll w[M*3];
    void check(int a,int b,int x){
        ll num=(ll)a*n+b;
        int cc=num%mod;
        for(int i=fir[cc];i;i=nex[i])
            if(w[i]==num){
                add(v[i],x);
                add(x,v[i]);
                return;
            }
        tot++;
        nex[tot]=fir[cc];
        w[tot]=num;
        v[tot]=x;
        fir[cc]=tot;
    }
}h;
int bfs(int s){
    memset(dis,127,sizeof(dis));
    queue<int> q;
    dis[s]=0;
    q.push(s);
    int res=0;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        res=u;
        for(int i=fir[u];i;i=e[i].nex){
            int v=e[i].v;
            if(dis[v]>dis[u]+1){
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
    }
    return res;
}
int main(){
    freopen("data.in","r",stdin);//
    scanf("%d",&n);
    for(int i=1;i<=n-2;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(b>c) swap(b,c);
        if(a>c) swap(a,c);
        if(a>b) swap(a,b);
        h.check(a,b,i);
        h.check(a,c,i);
        h.check(b,c,i);
    }
    int u=bfs(1);
    printf("%d\n",dis[bfs(u)]+1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SmallSXJ/article/details/73286982