思路:
1.如何判断是否在同一个史莱姆中:并查集
2.史莱姆队列使用链表,链表头是最左边的史莱姆,使用fa[]存储(类似并查集的p[]),链表尾是最右边的史莱姆,使用so[]存储。
例如样例1:
1 4 :将1和4集合合并,并令此集合fa[1]=fa[4]=1,so[1]=so[4]=4,集合内1->4
2 5 :将2和5集合合并,并令此集合fa[2]=fa[5]=2,so[2]=so[5]=5,集合内2->5
3 1:将3和1集合合并,并令此集合fa[1]=find(3)=3,so[3]=so[find(1)]=so[1]=4,集合内3->1->4
4 5:将4和5集合合并,并令此集合fa[5]=find(4)=3,so[4]=so[find(5)]=so[2]=5,集合内3->1->4->2->5
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, fa[N], so[N], nxt[N]; // fa:集合最左元素 so:集合最右元素
void init(int n)
{
for (int i = 1; i <= n; i++)
{
fa[i] = i;
so[i] = i;
}
}
int find(int x)
{
if (fa[x] != x)
fa[x] = find(fa[x]);
return fa[x];
}
void merge(int i, int j)
{
int x = find(i), y = find(j);
if (x == y)
return;
nxt[so[x]] = y; // x集合的最右元素指向y集合的最左元素
fa[y] = x; // y集合的最左元素更新为x集合的最左元素
so[x] = so[y]; // x集合的最右元素更新为y集合的最右元素
}
int main()
{
cin >> n;
init(n);
for (int i = 1; i <= n - 1; i++)
{
int x, y;
cin >> x >> y;
merge(x, y);
}
for (int i = find(1); i; i = nxt[i])
{ // 这里int i=find几也行,因为最后find()总是返回链表最左边的元素
cout << i << ' ';
}
return 0;
}