#includeusing namespace std;typedef long long ll;int a[200005]; //存放原始数据int vis[200005]; //标记选的对手int b[200005]; //答案序列queue q; //把所有能够选的都存一次,接着遍历与它有关系的。int main(){ int n,x; scanf("%d",&n); memset(vis,0,sizeof(vis)); //初始化 memset(b,0,sizeof(b)); //memset(a,0,sizeof(a)); for(int i = 1; i <= 2*n; i ++) { scanf("%d",&a[i]); vis[a[i]]++; } for(int i = 1; i <= 2*n; i ++) // 把能够选的放入到队列中,遍历与它相连的是否可以选上 { if(vis[i] == 0) q.push(i); } while(!q.empty()) { int x = q.front(); q.pop(); b[x] = 1; // 表示可以选择放入到S中 if(b[a[x]]==-1) // 如果x被选上了,那么x所选的对手被处理过一次不能选,跳过就可以 continue; //因为不跳出,vis会再重复减一次,导致答案会增多或者减少一些 b[a[x]] = -1; vis[a[a[x]]] --; // x选的对手y,y选的对手要减1,因为x被选进S中,y现在就相当于x的位置,y的选的对手就可以放进S中 if(vis[a[a[x]]] == 0) //当vis[z = a[a[x]]]为0,说明没有人挑战z,所以z要放进S中 q.push(a[a[x]]); } for(int i=1; i<=2*n; i++) { if(i<=n&&b[i]>=0) // 在第一房间(排)中,只要符合不与下面的在一个集合中就可以选择 printf("%d ",i); else if(b[i]==1) printf("%d ",i); } printf("\n"); return 0;}