http://codeforces.com/contest/761/problem/E
题意:
给出一棵树,现在要把这棵树上的结点放置在笛卡尔坐标上,使得每一条边与x轴平行或者与y轴平行。输出可行解,即每个点放置的坐标。
思路:
一开始我想,这个每条边的边长都是可长可短的,好像很麻烦啊。
做法还是很巧妙的,因为最多也就30个点,所以我们直接让该点连接的边未len长度,然后dfs它的子节点并使它的子节点的边长为len/2。你会发现,这样线段就不会相交了。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cstdio> 7 using namespace std; 8 9 const int maxn=30+5; 10 11 int n; 12 vector<int> g[maxn]; 13 int vis[maxn]; 14 long long ans_x[maxn],ans_y[maxn]; 15 16 int dx[]={0,-1,1,0}; 17 int dy[]={-1,0,0,1}; 18 19 void dfs(int u,int fa_dir,long long dir) 20 { 21 vis[u]=1; 22 int k=0; 23 for(int i=0;i<g[u].size();i++) 24 { 25 int v=g[u][i]; 26 if(!vis[v]) 27 { 28 if(k==3-fa_dir) k++; 29 ans_x[v]=ans_x[u]+dir*dx[k]; 30 ans_y[v]=ans_y[u]+dir*dy[k]; 31 dfs(v,k,dir/2); 32 k++; 33 } 34 } 35 } 36 37 int main() 38 { 39 while(~scanf("%d",&n)) 40 { 41 bool flag=true; 42 for(int i=1;i<=n;i++) g[i].clear(); 43 for(int i=0;i<n-1;i++) 44 { 45 int u,v; 46 scanf("%d%d",&u,&v); 47 g[u].push_back(v); 48 g[v].push_back(u); 49 if(g[u].size()>4 || g[v].size()>4) flag=false; 50 } 51 if(!flag) {puts("NO");continue;} 52 memset(vis,0,sizeof(vis)); 53 ans_x[1]=0; ans_y[1]=0; 54 dfs(1,-1,1<<30); 55 puts("YES"); 56 for(int i=1;i<=n;i++) 57 printf("%lld %lld ",ans_x[i],ans_y[i]); 58 } 59 return 0; 60 }