[ICPC2020南京D] Degree of Spanning Tree - 树
[ICPC2020南京D] Degree of Spanning Tree - 树
Description
给定无向图,如果有解,构造最大度不超过 \(n/2\) 的生成树。
Solution
任意找一棵生成树然后调整,对于度数大于 n/2 的点做调整,枚举与 p 关联的非树边,加入后删除环上一条边,如果这样导致了另一个点度数爆炸那么这两个点显然相邻,去掉这条边再换入一条新边即可
事实上可以随机 DFS 生成 100 个生成树
#include
using namespace std;
#define int long long
const int N = 1e5 + 5;
int n, m, deg[N];
vector> ans;
vector g[N];
int vis[N], tot;
void dfs(int p)
{
vis[p] = 1;
++tot;
random_shuffle(g[p].begin(), g[p].end());
for (int q : g[p])
{
if (deg[p] >= n / 2)
break;
if (vis[q] == 0)
{
ans.push_back({p, q});
deg[p]++;
deg[q]++;
dfs(q);
}
}
}
bool fuck()
{
for (int i = 1; i <= n; i++)
deg[i] = 0,
vis[i] = 0;
tot = 0;
dfs(rand() * rand() % n + 1);
if (tot == n)
return true;
return false;
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
g[i].clear();
}
ans.clear();
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= 99; i++)
{
if (fuck())
{
cout << "Yes" << endl;
for (auto [x, y] : ans)
cout << x << " " << y << endl;
return;
}
else
{
ans.clear();
}
}
cout << "No" << endl;
}
signed main()
{
srand(time(0));
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
solve();
}