在维护并查集的同时,维护每个线段的左顶点和右顶点。每次输入x和y,都把y的父节点定为x,最后所有数字的父节点都是最左边的数字。记录下线段x右顶点r的下一个值是y的左顶点l,并且在合并的时候改变区间的左右顶点,合并x,y所在集合。
最后发现左顶点未被改变的线段的l是第一个点。
#include<bits/stdc++.h> using namespace std; struct segment{ int l; int r; }seg[150010]; int fa[150010]; int nxt[150010]; int find(int x) { if(x==fa[x]) return x; else return fa[x]=find(fa[x]); } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { seg[i].l=i; seg[i].r=i; fa[i]=i; } for(int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); x=find(x); y=find(y); fa[y]=x; nxt[ seg[x].r ]=seg[y].l; seg[x].r=seg[y].r; seg[y].l=seg[x].l; } //printf("****\n"); int index=0; for(int i=1;i<=n;i++) { //printf("%d %d\n",seg[i].l,seg[i].r); if(seg[i].l==i) { index=i; break; } } int now=seg[index].l; while(now!=0) { printf("%d ",now); now=nxt[now]; } printf("\n"); }