zoj 3820 求三遍树的中心

题意:给一颗节点数>=2的树,在树上标记两个点,使得所有点到离它最近的点的最大距离最小。

这题需要了解树的直径以及树的中心这两个概念
树的中心是树上所有点到这个点的最大距离最小
树的直径是树的最长链
我的做法是,先找到树的中心,如果中心有两个(树的中心一定不会大于2个),就劈成两个子树,求两个子树的中心
如果树的中心有一个,就劈开直径上一条边,拆成两颗子树,求这两棵子树的中心。
代码复用性比较挫。。一份个代码写了6遍。。
代码:

//author: CHC
//First Edit Time:  2015-08-15 09:45
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=200000+1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
struct Edge {
    int to,next;
    Edge(){}
    Edge(int _to,int _next):to(_to),next(_next){}
}e[MAXN*2];
int head[MAXN],tot;
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}
void AddEdge(int u,int v){
    e[tot]=Edge(v,head[u]);
    head[u]=tot++;
    e[tot]=Edge(u,head[v]);
    head[v]=tot++;
}
int dis[MAXN],vis[MAXN],pre[MAXN],du[MAXN];
int mainpath[MAXN];
void bfs(int x,int flag,int y){
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    memset(du,0,sizeof(du));
    queue <int> q;
    q.push(x);
    vis[x]=1;
    dis[x]=1;
    pre[x]=x;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=head[now];~i;i=e[i].next){
            int next=e[i].to;
            if(flag&&next==y)continue;
            if(vis[next])continue;
            du[now]++;du[next]++;
            vis[next]=1;
            dis[next]=dis[now]+1;
            pre[next]=now;
            q.push(next);
        }
    }
}
int vis2[MAXN];
void bfs1(int x){
    memset(vis2,0,sizeof(vis2));
    memset(dis,0,sizeof(dis));
    dis[x]=1;
    queue <int> q;
    q.push(x);
    vis2[x]=1;
    pre[x]=x;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=head[now];~i;i=e[i].next){
            int next=e[i].to;
            if(vis[next]&&!vis2[next]){
                //printf("%d --> %d\n",now,next);
                vis2[next]=1;
                dis[next]=dis[now]+1;
                pre[next]=now;
                q.push(next);
            }
        }
    }
}
int hpath[MAXN];
void getmainpath(int x){
    memset(hpath,0,sizeof(hpath));
    mainpath[0]=0;
    while(pre[x]!=x){
        mainpath[++mainpath[0]]=x;
        hpath[x]=1;
        //printf("x:%d\n",x);
        x=pre[x];
    }
        //printf("x:%d\n",x);
    mainpath[++mainpath[0]]=x;
    hpath[x]=1;
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        init();
        for(int i=0,x,y;i<n-1;i++){
            scanf("%d%d",&x,&y);
            AddEdge(x,y);
        }
        /*
        if(n==2){
            puts("0 1 2");
            continue;
        }
        else if(n==3){
            puts("1 1 2");
            continue;
        }
        */
        int maxdis=0,maxu;
        bfs(1,0,0);
        int tu=1;
        for(int i=1;i<=n;i++){
            if(du[i]==1){
                tu=i;break;
            }
        }
        bfs1(tu);
        maxdis=0;
        for(int i=1;i<=n;i++){
            if(maxdis<dis[i]){
                maxu=i;maxdis=dis[i];
            }
        }
        //printf("maxdis%d %d\n",maxdis,maxu);
        bfs1(maxu);
        maxdis=0;
        for(int i=1;i<=n;i++){
            if(maxdis<dis[i]){
                maxu=i;maxdis=dis[i];
            }
        }

        getmainpath(maxu);
        int ans1,ans2;
        int dis1,dis2;
        //printf("maxdis%d %d\n",maxdis,maxu);
        //system("pause");
        if(maxdis%2==0){
            int mid=maxdis/2;
            int midl=mid;
            int midr=midl+1;
            int midu,midv;
            //printf("midlr:%d %d %d\n",mid,midl,midr);
            for(int i=1;i<=mainpath[0];i++){
                //printf("%d:%d ",mainpath[i],dis[mainpath[i]]);
                if(dis[mainpath[i]]==midl){
                    midu=mainpath[i];
                }
                if(dis[mainpath[i]]==midr){
                    midv=mainpath[i];
                }
            }
            //printf("miduv:%d %d\n",midu,midv);
            while(midu==midv);
            bfs(midu,1,midv);
            int tu=midu;
            for(int i=1;i<=n;i++){
                if(vis[i]&&du[i]==1){
                    tu=i;break;
                }
            }
            bfs1(tu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(dis[i]>maxdis){
                    maxdis=dis[i];maxu=i;
                }
            }
            bfs1(maxu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(dis[i]>maxdis){
                    maxdis=dis[i];maxu=i;
                }
            }
            getmainpath(maxu);
            for(int i=1;i<=mainpath[0];i++){
                if(dis[mainpath[i]]==maxdis/2+1){
                    ans1=mainpath[i];
                }
            }
            dis1=maxdis/2;
            //printf("ans1:%d\n",ans1);

            bfs(midv,1,midu);
            tu=midv;
            for(int i=1;i<=n;i++){
                if(vis[i]&&du[i]==1){
                    tu=i;break;
                }
            }
            bfs1(tu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(dis[i]>maxdis){
                    maxdis=dis[i];maxu=i;
                }
            }
            bfs1(maxu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(dis[i]>maxdis){
                    maxdis=dis[i];maxu=i;
                }
            }
            getmainpath(maxu);
            for(int i=1;i<=mainpath[0];i++){
                if(dis[mainpath[i]]==maxdis/2+1){
                    ans2=mainpath[i];
                }
            }
            dis2=maxdis/2;
            printf("%d %d %d\n",max(dis1,dis2),ans1,ans2);
        }
        else {
            int mid=maxdis/2+1;
            int midu,midv;
            //printf("mid:%d\n",mid);
            for(int i=1;i<=mainpath[0];i++){
                if(dis[mainpath[i]]==mid){
                    midu=mainpath[i];
                }
            }
            //printf("midu:%d\n",midu);
            midv=midu;
            for(int i=head[midu];~i;i=e[i].next){
                if(hpath[e[i].to]){
                    midv=e[i].to;break;
                }
            }
            while(midu==midv);
            //printf("midu:%d midv:%d\n",midu,midv);
            bfs(midu,1,midv);
            int tu=midu;
            for(int i=1;i<=n;i++){
                if(vis[i]&&du[i]==1){
                    tu=i;break;
                }
            }
            //printf("tu:%d\n",tu);
            bfs1(tu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(maxdis<dis[i]){
                    maxdis=dis[i];
                    maxu=i;
                }
            }
            bfs1(maxu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(maxdis<dis[i]){
                    maxdis=dis[i];
                    maxu=i;
                }
            }
            getmainpath(maxu);
            //printf("maxu:%d %d\n",maxu,maxdis/2+1);
            for(int i=1;i<=mainpath[0];i++){
                //printf("%d:%d ",i,dis[i]);
                if(dis[mainpath[i]]==maxdis/2+1){
                    //printf("here:%d\n",i);
                    ans1=mainpath[i];
                }
            }
            //puts("");
            //printf("ans1:%d\n",ans1);
            dis1=maxdis/2;

            bfs(midv,1,midu);
            tu=midv;
            for(int i=1;i<=n;i++){
                if(vis[i]&&du[i]==1){
                    tu=i;break;
                }
            }
            //printf("tu:%d\n",tu);
            bfs1(tu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(maxdis<dis[i]){
                    maxdis=dis[i];
                    maxu=i;
                }
            }
            bfs1(maxu);
            maxdis=0;
            for(int i=1;i<=n;i++){
                if(maxdis<dis[i]){
                    maxdis=dis[i];
                    maxu=i;
                }
            }
            getmainpath(maxu);
            //printf("maxu:%d\n",maxu);
            for(int i=1;i<=mainpath[0];i++){
                if(dis[mainpath[i]]==maxdis/2+1){
                    ans2=mainpath[i];
                }
            }
            dis2=maxdis/2;
            printf("%d %d %d\n",max(dis1,dis2),ans1,ans2);
        }
    }
    return 0;
}
/*
8
1 2
1 3
1 4
2 7
2 8
3 5
5 6

10
1 2
2 3
3 10
1 4
4 5
1 8
8 9
1 6
6 7

13
1 2
2 3
3 10
1 4
4 5
1 8
8 9
1 6
6 7
10 11
11 12
12 13

11
1 2
2 3
3 4
4 5
5 6
6 7
7 8
6 9
9 10
10 11
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值