思路:
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;
}