题解:P11829 [TOIP2024] 栖息地分配
必然有解。
当图中有
否则,当图中仅有一个连通块时,由于
#include <bits/stdc++.h>
using namespace std;
namespace z {
#define int long long
const int N = 5e5 + 5;
int fa[N], flag[N], vis[N];
vector<int> p[N];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
void merge(int x, int y) { x = find(x), y = find(y); if(x != y) fa[x] = y; }
void init(int n) { for(int i = 1; i <= n; i++) fa[i] = i, flag[i] = 0, vis[i] = 0, p[i].clear(); }
void dfs(int u, int fa) {
vis[u] = 1;
for(auto v : p[u]) {
if(v == fa) continue;
if(vis[v]) merge(v, u);
else dfs(v, u);
}
}
void solve() {
int n, m; cin >> n >> m;
init(n);
for(int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
p[u].push_back(v);
p[v].push_back(u);
}
dfs(1, 0);
for(int i = 2; i <= n; i++) if(!vis[i]) {
vector<int> a1, a2;
for(int j = 1; j <= n; j++) {
if(vis[j]) a1.push_back(j);
else a2.push_back(j);
}
if(a1.size() == 1) {
cout << 1 << " " << a1[0] << '\n';
cout << 1 << " " << a2[0] << '\n';
cout << a2.size() - 1 << " ";
for(auto j : a2) if(j != a2[0]) cout << j << ' ';
cout << '\n';
} else if(a2.size() == 1) {
cout << 1 << " " << a1[0] << '\n';
cout << 1 << " " << a2[0] << '\n';
cout << a1.size() - 1 << " ";
for(auto j : a1) if(j != a1[0]) cout << j << ' ';
} else {
cout << a1.size() << " ";
for(auto j : a1) cout << j << ' ';
cout << '\n';
cout << 1 << " " << a2[0] << '\n';
cout << a2.size() - 1 << " ";
for(auto j : a2) if(j != a2[0]) cout << j << ' ';
}
return;
}
vector<int> ans;
for(int i = 1; i <= n; i++)
if(find(i) == i) ans.push_back(i);
vector<int> a[3];
for(int i = 0; i <= 2; i++)
for(int j = 1; j <= n; j++)
if(find(j) == ans[i])
a[i].push_back(j), flag[j] = 1;
for(int i = 1; i <= n; i++)
if(!flag[i]) a[0].push_back(i);
for(int i = 0; i <= 2; i++) {
cout << a[i].size() << ' ';
for(auto j : a[i]) cout << j << ' ';
cout << '\n';
}
}
void main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);cout.tie(nullptr);
int T; cin >> T;
while(T--) solve();
}
#undef int
}
int main()
{
z::main();
return 0;
}