思路:
无解显然等价于存在点度大于 \(4\) 的节点,因为与 \((x,y)\) 关于坐标轴平行的点满足边不相交只有 \(4\) 个
钦定 \(1\) 为根
第一反应是边权要尽量大,要不然容易出现兄弟节点重合的情况,但由于边不能相交,所以边权要随着树的层数的增加不断减小,假设深度为 \(d\),\(i\) 和它子节点的连边的权值是 \(p_i\),那么应该满足对于任意 \(i\) ,都有 \(p_i > \sum_{i< k \leq d} p_k\),满足这个等式的构造方法是显然的,即对于任意 \(1\leq i\leq d\),满足\(p_i=2^{n-i+1}\),因为 \(n\) 很小,所以不必担心跑出 \(10^{18}\)。
现在每条边的权值已经得到,还需要考虑 \(u\) 的子节点的方向不能朝向 \(u\) 的父节点,记录来的方向即可。
代码:
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define ld long double
using namespace std;
int n,d[50];
bool f=0;
vector<int>edge[50];
struct node
{
int x,y;
};
node p[50];
map<pair<int,int>,bool>m;
void dfs(int u,int fa,int len,int from)
{
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(v==fa) continue;
int f;
if(!m[make_pair(p[u].x,p[u].y+len)]&&from!=4) p[v]=(node){p[u].x,p[u].y+len},m[make_pair(p[u].x,p[u].y+len)]=1,f=1;
else if(!m[make_pair(p[u].x,p[u].y-len)]&&from!=1) p[v]=(node){p[u].x,p[u].y-len},m[make_pair(p[u].x,p[u].y-len)]=1,f=4;
else if(!m[make_pair(p[u].x+len,p[u].y)]&&from!=3) p[v]=(node){p[u].x+len,p[u].y},m[make_pair(p[u].x+len,p[u].y)]=1,f=2;
else if(!m[make_pair(p[u].x-len,p[u].y)]&&from!=2) p[v]=(node){p[u].x-len,p[u].y},m[make_pair(p[u].x-len,p[u].y)]=1,f=3;
dfs(v,u,len/2,f);
}
}
signed main()
{
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
edge[u].push_back(v);
edge[v].push_back(u);
d[u]++,d[v]++;
}
for(int i=1;i<=n;i++)
{
if(d[i]>4) f=1;
}
if(f==1) puts("NO");
else
{
puts("YES");
p[1]=(node){0,0};m[make_pair(0,0)]=1;
dfs(1,0,2147483647,0);
// for(int i=1;i<=n;i++) cout<<d[i]<<" ";
// puts("");
for(int i=1;i<=n;i++) cout<<p[i].x<<" "<<p[i].y<<"\n";
}
}