Codeforces Round #529 (Div. 3) D. Circular Dance
题意:
有 n 个孩子编号为 1~n ,绕着圣诞树 dance;
编号为 i 的孩子可以记住ai1,ai2两个小孩,ai1,ai2是 i 在顺时针方向的相邻的两个小孩,但ai1,ai2不一定是按顺时针方向排列的;
给出每个孩子相邻两个孩子的信息,让你还原这个序列。
题解:
可以以任一孩子作为第一个孩子,假设以编号 1 为第一个,编号1有两个相邻的孩子信息 a,b
如果 b 在 a 的顺时针方向,那么第二个孩子就是 a,反之为 b。
确定了前两个孩子后
i 从 1 开始遍历,第 i 个孩子的两个相邻的孩子a,b已经确定一个在 i+1 位置了,那么剩下的那个肯定在 i+2 位置,遍历到 n-2 却id确定最终序列。
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 const int maxn=2e5+10; 7 8 int n; 9 struct Node 10 { 11 int a,b;//i的顺时针方向相邻的两个孩子 12 Node(int _a=0,int _b=0):a(_a),b(_b){} 13 }nex[maxn]; 14 bool vis[maxn]; 15 int q[maxn]; 16 17 void Solve() 18 { 19 mem(vis,false); 20 21 q[1]=1; 22 int x=nex[1].a,y=nex[1].b; 23 q[2]=(nex[x].a == y || nex[x].b == y ? x:y);//确定第二个位置的孩子的编号 24 vis[q[1]]=true,vis[q[2]]=true; 25 for(int i=1;i <= n-2;++i) 26 { 27 x=nex[q[i]].a; 28 y=nex[q[i]].b; 29 q[i+2]=(!vis[x] ? x:y); 30 vis[q[i+2]]=true; 31 } 32 for(int i=1;i <= n;++i) 33 printf("%d ",q[i]); 34 } 35 int main() 36 { 37 scanf("%d",&n); 38 for(int i=1;i <= n;++i) 39 { 40 int a,b; 41 scanf("%d%d",&a,&b); 42 nex[i]=Node(a,b); 43 } 44 Solve(); 45 return 0; 46 }
根据大神代码改编的简介代码%%%%%
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=2e5+10; 5 6 int n; 7 int a[maxn]; 8 int b[maxn]; 9 bool vis[maxn]; 10 11 int Find(int nex1,int nex2) 12 { 13 return !vis[nex1] && (a[nex1] == nex2 || b[nex1] == nex2) ? 0:1; 14 } 15 void Solve() 16 { 17 int x=1; 18 for(int i=1;i <= n;++i) 19 { 20 printf("%d ",x); 21 vis[x]=true; 22 int nex[2]={a[x],b[x]}; 23 x=nex[Find(nex[0],nex[1])]; 24 } 25 } 26 int main() 27 { 28 scanf("%d",&n); 29 for(int i=1;i <= n;++i) 30 scanf("%d%d",a+i,b+i); 31 Solve(); 32 return 0; 33 }