题意:
给定一棵n个点的树,给定平面上n个点,将n个点用线段连起来画成树的形状,使得不存在不在端点相交的线段,构造出一种情况。
解法:
首先观察我们常规画出来的树形图可知,树的子树是根据极角分开的,这样,我们每一次找到最靠左下的点,
而后对剩余点极角排序,根据子树大小和极角的连续关系将点集划分,依次递归即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 7 #define N 1510 8 #define LL long long 9 #define p E[i].x 10 #define LD double 11 #define pi acos(-1) 12 13 using namespace std; 14 15 struct edge 16 { 17 int x,to; 18 }E[N<<1]; 19 20 struct node 21 { 22 LL x,y; 23 LD v; 24 int id; 25 void scan() 26 { 27 scanf("%I64d%I64d",&x,&y); 28 } 29 }a[N],ans[N],root; 30 31 int n,totE; 32 int g[N],fa[N],siz[N],ansv[N]; 33 34 void addedge(int x,int y) 35 { 36 E[++totE]=(edge){y,g[x]}; g[x]=totE; 37 E[++totE]=(edge){x,g[y]}; g[y]=totE; 38 } 39 40 void dfs(int x) 41 { 42 siz[x]=1; 43 for(int i=g[x];i;i=E[i].to) 44 if(p!=fa[x]) 45 { 46 fa[p]=x; 47 dfs(p); 48 siz[x]+=siz[p]; 49 } 50 } 51 52 bool cmp(node a,node b) 53 { 54 LL tmp1=(a.x-root.x)*(b.y-root.y); 55 LL tmp2=(a.y-root.y)*(b.x-root.x); 56 return tmp1<tmp2; 57 } 58 59 void solve(int x,int l,int r) 60 { 61 int t=l; 62 for(int i=l+1;i<=r;i++) 63 if(a[i].x<a[t].x || (a[i].x==a[t].x && a[i].y<a[t].y)) 64 t=i; 65 swap(a[t],a[l]); 66 root=ans[x]=a[l]; 67 l++; 68 if(l>r) return; 69 sort(a+l,a+r+1,cmp); 70 for(int i=g[x];i;i=E[i].to) 71 if(p!=fa[x]) 72 { 73 solve(p,l,l+siz[p]-1); 74 l=l+siz[p]; 75 } 76 } 77 78 int main() 79 { 80 while(~scanf("%d",&n)) 81 { 82 for(int i=1;i<=n;i++) g[i]=0; 83 totE=0; 84 for(int i=1,x,y;i<n;i++) 85 { 86 scanf("%d%d",&x,&y); 87 addedge(x,y); 88 } 89 dfs(1); 90 for(int i=1;i<=n;i++) 91 { 92 a[i].scan(); 93 a[i].id=i; 94 } 95 solve(1,1,n); 96 for(int i=1;i<=n;i++) ansv[ans[i].id]=i; 97 for(int i=1;i<=n;i++) printf("%d ",ansv[i]); 98 printf("\n"); 99 } 100 return 0; 101 }
原文:http://www.cnblogs.com/lawyer/p/6523285.html