2018-2019 ICPC Northwestern European Regional Programming Contest (NWERC 2018)
题意:给你一棵有n个节点的树,要你在一个二维平面用n个点表示出这棵树,使得边的大小为1,边与边之间不能交叉,点不能重合。
槽点:1、比赛时th的值设为了2*pi/n导致wa3..wa3..wa3..wa到自闭
得设为pi/n的原因是不让儿子返回到父亲的方向导致边交叉
2、题解好像说点输出要多输出小数点后几位,但是因为最开始就是输出10位所以没出现关于这个的问题
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e4+5; const int MAX=4e6+9; const int mod=1e9+7; const double ep1=1e-7; const double ep2=1e-3; const double pi=acos(-1); #define pb push_back /* 因为边距离为1所以也可以把向量旋转写成a.x+cos(ang),a.y+sin(ang) */ struct point{ double x,y; point(){} point(double x,double y):x(x),y(y){} }p[maxn],ans[maxn]; point operator-(point a,point b) { return point(a.x-b.x,a.y-b.y); } //p代表该点与父亲的向量,ans记录这个点的位置 #define Vector point Vector Rotate(Vector a,double rad) { return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)); } vector<int>vec[maxn]; int n; int siz[maxn]; double th; void dfs(int x,int pre)//可以只用一个dfs,但是最开始这么写了就懒得改了 { int si=vec[x].size(); for(int i=0;i<si;i++) { int to=vec[x][i]; if(to==pre)continue; dfs(to,x); siz[x]+=siz[to]; } siz[x]++; } void dfs1(int x,int pre) { int si=vec[x].size(); Vector v=p[x]; point pp; for(int i=0;i<si;i++) { int to=vec[x][i]; if(to==pre)continue; pp.x=ans[x].x+v.x; pp.y=ans[x].y+v.y; ans[to]=pp; p[to]=pp-ans[x]; dfs1(to,x); v=Rotate(v,th*siz[to]); } } void solve() { scanf("%d",&n); for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); vec[a].pb(b); vec[b].pb(a); } dfs(1,-1); th=pi/n; int si=vec[1].size(); ans[1].x=ans[1].y=0; Vector v; point pp; v.x=1,v.y=0; for(int i=0;i<si;i++) { int to=vec[1][i]; pp.x=v.x;pp.y=v.y; ans[to]=pp; p[to]=pp; dfs1(to,1); v=Rotate(v,th*siz[to]); } for(int i=1;i<=n;i++)printf("%.10f %.10f\n",ans[i].x,ans[i].y); } int main() { int _=1; // scanf("%d",&_); while(_--)solve(); return 0; }
欢迎加我qq1165750856一起玩呀~