F2. Spanning Tree with One Fixed Degree
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an undirected unweighted connected graph consisting of nn vertices and mm edges. It is guaranteed that there are no self-loops or multiple edges in the given graph.
Your task is to find any spanning tree of this graph such that the degree of the first vertex (vertex with label 11 on it) is equal to DD (or say that there are no such spanning trees). Recall that the degree of a vertex is the number of edges incident to it.
Input
The first line contains three integers nn, mm and DD (2≤n≤2⋅1052≤n≤2⋅105, n−1≤m≤min(2⋅105,n(n−1)2),1≤D<nn−1≤m≤min(2⋅105,n(n−1)2),1≤D<n) — the number of vertices, the number of edges and required degree of the first vertex, respectively.
The following mm lines denote edges: edge ii is represented by a pair of integers vivi, uiui (1≤vi,ui≤n1≤vi,ui≤n, ui≠viui≠vi), which are the indices of vertices connected by the edge. There are no loops or multiple edges in the given graph, i. e. for each pair (vi,uivi,ui) there are no other pairs (vi,uivi,ui) or (ui,viui,vi) in the list of edges, and for each pair (vi,ui)(vi,ui) the condition vi≠uivi≠ui is satisfied.
Output
If there is no spanning tree satisfying the condition from the problem statement, print "NO" in the first line.
Otherwise print "YES" in the first line and then print n−1n−1 lines describing the edges of a spanning tree such that the degree of the first vertex (vertex with label 11 on it) is equal to DD. Make sure that the edges of the printed spanning tree form some subset of the input edges (order doesn't matter and edge (v,u)(v,u) is considered the same as the edge (u,v)(u,v)).
If there are multiple possible answers, print any of them.
Examples
input
Copy
4 5 1 1 2 1 3 1 4 2 3 3 4
output
Copy
YES 2 1 2 3 3 4
input
Copy
4 5 3 1 2 1 3 1 4 2 3 3 4
output
Copy
YES 1 2 1 3 4 1
input
Copy
4 4 3 1 2 1 4 2 3 3 4
output
Copy
NO
Note
The picture corresponding to the first and second examples:
The picture corresponding to the third example:
对于与1相连的每个点,如果其中有两个点可以通过不经过1的路径相连的话,那么将这两个点划分到一个集合里面。
显然,对于一个集合里面的所有元素,只要有一个点与1相连,那么其他点就能够与1相连,那么这些边就是可变动的。
设集合的个数为a,在原图中度为b,那么只有当k满足a<=k<=b时,才可以满足题意。接下来就可以在保留每个集合至少留一条边的情况下通过删边使1的度为k。然后bfs跑完一颗树即可。
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
vector<int>v[200004];
set<int>top;
bool vis[200004];
int fa[200004];
int Find(int a)
{
if(a==fa[a])return a;
else return fa[a]=Find(fa[a]);
}
void dfs(int u)//判连通
{
for (int i = 0; i < v[u].size(); ++i) {
if(v[u][i]==1)continue;
if(vis[v[u][i]])continue;
vis[v[u][i]]=1;
if(top.count(v[u][i]))
{
int fx=Find(u),fy=Find(v[u][i]);
if(fx!=fy)
{
fa[fy]=fx;
}
}
dfs(v[u][i]);
}
}
int main()
{
int n,m,d;
memset(vis,0, sizeof(vis));
for (int i = 0; i <= 200000; ++i) {
fa[i]=i;
}
cin>>n>>m>>d;
int x,y;
for (int i = 0; i < m; ++i) {
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
if(x==1)top.insert(y);
if(y==1)top.insert(x);
}
for (auto i = top.begin(); i!=top.end() ; ++i) {
if(fa[*i]==*i)
{
vis[*i]=1;
dfs(*i);
}
}
vector<int>ct;
for (auto i = top.begin(); i!=top.end() ; ++i) {
if(fa[*i]==*i)ct.push_back(*i);
}
if(d>top.size()||d<ct.size())
{
puts("NO");
}
else
{
puts("YES");
int num=top.size();
for (int i = 0; i < v[1].size()&&num>d; ++i) {
if(fa[v[1][i]]!=v[1][i])
{
v[1].erase(v[1].begin()+i--);
num--;
}
}
queue<int>q;
q.push(1);
memset(vis,0, sizeof(vis));
vis[1]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
for (int i = 0; i < v[t].size(); ++i) {
int u=v[t][i];
if(vis[u])continue;
printf("%d %d\n",t,u);
vis[u]=1;
q.push(u);
}
}
}
}