【poj3099】求树的重心

poj3099

大概意思就是给你一棵树,让你求它的重心。

【如果你是来找题解的建议直接去看代码 ↓】

我们是现学现用的……
树的重心,也就是求树上一点,使这个点到树上其他点的路径最大值最小。
【百度了一下,关于树的重心是啥意思,各位神犇都有自己的说法,但本质好像是一样的】
显然,重心必定在树的直径上。树的重心要么一个,要么两个。

所以,我们只需要找到树的直径并且记录路径,然后找到直径的中点。
①若中点和某个点重合,则这个点是重心。
②若落在一条边上,并且到离它最近的两点距离相同,则这两点都是重心。
③若在边上并且到离它最近的两点距离不相同,则离它近的那个点是重心。
(当然不带权的话只需要判断直径长度的奇偶性就好)

我当时看错题,当带权做的,结果傻X了,然后把权值改成1…所以说这份代码有些地方打的很傻,将就看吧(:з」∠)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int size=200010;
const int INF=233333333;
int n,head[size],nxt[size],tot=0,pre[size];
int dist[size];
struct edge{
    int t;
}l[size];

void build(int f,int t)
{
    l[++tot].t=t;
    nxt[tot]=head[f];
    head[f]=tot;
}

double getdist(int x1,int y1,int z1,int x2,int y2,int z2)
{
    return sqrt((double)(x1-x2)*(x1-x2)+(double)(y1-y2)*(y1-y2)+(double)(z1-z2)*(z1-z2));
}
struct input{
    int id,x,y,z;
}in[size]; 
queue<int> q;
bool use[size];
void bfs(int s)
{
    memset(pre,0,sizeof(pre));  
    memset(use,0,sizeof(use));  
    while(q.size()) q.pop();
    for(int i=1;i<=n;i++) dist[in[i].id]=INF;
    q.push(s);
    dist[s]=0;
    while(q.size())
    {
        int f=q.front(); q.pop();
        if(use[f]) continue;
        use[f]=1;
        for(int i=head[f];i;i=nxt[i])
        {
            int v=l[i].t;
            if(dist[v]>dist[f]+1)
            {
                dist[v]=dist[f]+1;
                pre[v]=f;
                q.push(v);
            }
        }
    }
/* puts(""); for(int i=1;i<=n;i++) { cout<<dist[in[i].id]<<" "; } puts("");*/
}

int getmax()
{
    int maxn=0;
    int k=0;
    for(int i=1;i<=n;i++)
    {
        if(dist[in[i].id]>maxn)
        {
            maxn=dist[in[i].id];
            k=in[i].id;
        }
    }
    return k;
}

struct haha{
    int u;
    int d;
}a[size];
int len=0;
void dfs(int u)
{
    if(pre[u]) dfs(pre[u]);
    a[++len]=(haha){u,dist[u]};
}

void init()
{
    memset(nxt,0,sizeof(nxt));
    memset(head,0,sizeof(head));
    memset(pre,0,sizeof(pre));
    memset(a,0,sizeof(a));
    memset(l,0,sizeof(l));
    len=0;
    tot=0;
}

int main()
{
    while(~scanf("%d",&n)&&n)
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int id,x,y,z;
            scanf("%d%d%d%d",&in[i].id,&in[i].x,&in[i].y,&in[i].z);
        }
        for(int i=1;i<=n;i++)
        {
            double minn=233333333;
            int k=1;
            for(int j=1;j<i;j++)
            {
                double d=getdist(in[i].x,in[i].y,in[i].z,in[j].x,in[j].y,in[j].z);
                if(d<minn)
                {
                    minn=d;
                    k=j;
                }
            // cout<<" "<<d<<in[j].id<<" "<<k<<" "<<minn<<endl;

            }
            build(in[i].id,in[k].id);
            build(in[k].id,in[i].id);
        // cout<<in[i].id<<" "<<in[k].id<<endl;
        }       
        bfs(in[1].id);
        int k=getmax();
        bfs(k);
        k=getmax();
        dfs(k);
        double dd=dist[k]/2.0;
        int p;

    // for(int p=1;p<=len;p++) cout<<a[p].u<<" ";puts("");
    // for(int p=1;p<=len;p++) cout<<a[p].d<<" ";puts("");

        for(p=1;p<=len;p++)
        {
            if(a[p].d>=dd) break;
        }

        if(a[p].d==dd) printf("%d\n",a[p].u);
        else if(a[p].d-dd==dd-a[p-1].d) printf("%d %d\n",min(a[p-1].u,a[p].u),max(a[p-1].u,a[p].u));
        else if(a[p].d-dd>dd-a[p-1].d) printf("%d\n",a[p-1].u);
        else if(a[p].d-dd<dd-a[p-1].d) printf("%d\n",a[p].u);
    }
    return 0;
}

你可能感兴趣的:(poj,树的重心)