1. 程式人生 > >【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; }