题目链接:https://vjudge.net/contest/344327#problem/C
翻译:
给定一个排列(1~n),三个相连的数组成一个三元组,那么长度为n的排列,可以组成n-2个三元组。
例如1 2 3 4 5可以组成(1 2 3)(2 3 4)(3 4 5)三个三元组。
刚开始输入一个n,接下来给定n-2个三元组,可是这n-2个三元组,任意改变顺序,内部的三个数也任意改变顺序(但是保证这三个数仍然是相连的)。求一个符合条件的排列。
分析:
对于n-2个三元组,一定有两个数出现的次数为1,这两个数一定是排列的开头和结尾。
一定有两个数出现的次数为2,这两个数一定是排列开头的第二个数和结尾倒数第二个数。
别的数出现的次数为3次,且出现的三元组一定为3个。
对于每一个三元组,变换有3种。
找到开头(x)和第二个数(y)所在的三元组(另一个数为z),找到下一个三元组满足y和z在其中,同时保证另一个数不是x。
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e5+10;
vector<int>v[N];
int book[N],co[N];
int main()
{
int n;
memset(book,0,sizeof(book));
memset(co,0,sizeof(co));
scanf("%d",&n);
for(int i=1,x,y,z; i<=n-2; i++)
{
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(y),v[x].push_back(z);
v[y].push_back(x),v[y].push_back(z);
v[z].push_back(x),v[z].push_back(y);
book[x]++,book[y]++,book[z]++;
}
int t1,t2;
for(int i=1; i<=n; i++)/*找到开头*/
{
if(book[i]==1)
{
co[i]=1;
t1=i;
break;
}
}
for(int i=0;i<v[t1].size();i++)
{
if(book[v[t1][i]]==2)
{
t2=v[t1][i];
co[v[t1][i]]=1;
break;
}
}
printf("%d %d",t1,t2);
for(int i=3;i<=n;i++)
{
int tab;
for(int j=0;j<v[t1].size();j++)
{
if(!co[v[t1][j]])
{
printf(" %d",v[t1][j]);
co[v[t1][j]]=1;
tab=v[t1][j];
break;
}
}
t1=t2;
t2=tab;
}
return 0;
}