题意:给定一个n说明是一个有n个数字的序列,然后n行每行告诉你x前后的数字分别是啥,求这个序列的正确排列顺序,第一个数字前面是0,最后一个数字最后是0.
思路:我们可以先确定第一个数字,然后根据第一个数字后面来确定第三个、第五个...然后再找结尾是0的,回去跳着插空。如果是偶数的话这样刚刚好,但是如果是奇数个...两次就重复了。so,对于奇数我们可以确定第二个数字,就是没有以这个数字为后面的,那么这个数字就是第二个数字...然后再继续插空。
可以用并查集做,不过我用的是模拟+二分。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct node
{
int x,y;
}s[300000];
int used[1000600];
int a[300000],n;
int cmp1(const void *a,const void *b)
{
return (*(node*)a).x-(*(node*)b).x;
}
int cmp2(const void *a,const void *b)
{
return (*(node*)a).y-(*(node*)b).y;
}
int ef1(int x)
{
int low, high, mid ;
low = 0;
high = n-1;
while ( low <= high )
{
mid = (low + high) / 2;
if(x < s[mid].x)
{
high = mid - 1;
}
else if(x > s[mid].x)
{
low = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
int ef2(int x)
{
int low, high, mid ;
low = 0;
high = n-1;
while ( low <= high )
{
mid = (low + high) / 2;
if(x < s[mid].y)
{
high = mid - 1;
}
else if(x > s[mid].y)
{
low = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int i,j,k;
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(used,0,sizeof(used));
for(i=0;i<n;i++)
scanf("%d %d",&s[i].x,&s[i].y);
qsort(s,n,sizeof(node),cmp1);
j=0;i=2;
while(i<=n)//构造第1、3、5、7……个数
{
int x=ef1(j);
a[i]=s[x].y;
i=i+2;
j=s[x].y;
used[s[x].y]=1;
}
qsort(s,n,sizeof(node),cmp2);
i=n-1;j=0;
while(i>0)//从后往前构造倒数第1、3……个数
{
int x=ef2(j);
a[i]=s[x].x;
i=i-2;
j=s[x].x;
used[s[x].y]=1;
}
if(a[n]==0)//如果个数是奇数,那么上面两次操作重复
{
i=n-2;
for(k=0;k<n;k++)
{
if(used[s[k].y]==0)
break;
}
j=s[k].y;
while(1)
{
int x=ef2(j);
if(x==-1)
break;
j=s[x].x;
}
a[1]=j;i=3;//找出第二个数字。
qsort(s,n,sizeof(node),cmp1);
while(i<=n)//排序后构造第2、4、6……个数。
{
int x=ef1(j);
a[i]=s[x].y;
i=i+2;
j=s[x].y;
}
}
for(i=1;i<=n;i++)
{
if(i==1)
printf("%d",a[i]);
else
printf(" %d",a[i]);
}
printf("\n");
}