【poj3099】求樹的重心
阿新 • • 發佈:2019-02-11
大概意思就是給你一棵樹,讓你求它的重心。
【如果你是來找題解的建議直接去看程式碼 ↓】
我們是現學現用的……
樹的重心,也就是求樹上一點,使這個點到樹上其他點的路徑最大值最小。
【百度了一下,關於樹的重心是啥意思,各位神犇都有自己的說法,但本質好像是一樣的】
顯然,重心必定在樹的直徑上。樹的重心要麼一個,要麼兩個。
所以,我們只需要找到樹的直徑並且記錄路徑,然後找到直徑的中點。
①若中點和某個點重合,則這個點是重心。
②若落在一條邊上,並且到離它最近的兩點距離相同,則這兩點都是重心。
③若在邊上並且到離它最近的兩點距離不相同,則離它近的那個點是重心。
(當然不帶權的話只需要判斷直徑長度的奇偶性就好)
我當時看錯題,當帶權做的,結果傻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;
}