题意:给出n个人,他们有的人是朋友关系,现在他们要去吃饭,若某个人进入餐厅看不见朋友,则它伤心,要求求出一个序列,使这样进去,使伤心人数最少,若有多个,则按字典序输出。
思路:并查集判连通块,然后bfs+优先队列输出字典序。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int t, n, m, vis[N], d[N], num, h[N], ans;
priority_queue<int, vector<int>, greater<int> >q;
struct node {
int v, net;
} no[N << 2];
int F(int x) {
return d[x] == x ? x : d[x] = F(d[x]);
}
void add(int u, int v) {
no[num].v = v;
no[num].net = h[u];
h[u] = num++;
}
int main() {
int t;
cin >> t;
while(t--) {
while(!q.empty())
q.pop();
cin >> n >> m;
num = 0, ans = 0;
for(int i = 0; i <= n; i++) {
d[i] = i, vis[i] = 0, h[i] = -1;
}
for(int a, b, i = 0; i < m; i++) {
cin >> a >> b;
add(a, b);
add(b, a);
int x = F(a), y = F(b);
if(x != y) {
if(x < y)
d[y] = x;
else
d[x] = y;
}
}
for(int i = 1; i <= n; i++)
if(d[i] == i)
ans++;
cout << ans << endl;
for(int i = 1; i <= n; i++) {
int k = F(i);
if(vis[k] == 0) {
vis[k] = 1;
q.push(k);
}
}
int k = 0;
while(!q.empty()) {
int x = q.top();
k++;
if(k != n)
cout << x << " ";
else
cout << x << endl;
q.pop();
for(int i = h[x]; ~i; i = no[i].net) {
int v = no[i].v;
if(!vis[v]) {
vis[v] = 1;
q.push(v);
}
}
}
}
return 0 ;
}