Codeforces Round #544 (Div. 3) 1133-F2. Spanning Tree with One Fixed Degree

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);
            }
        }
    }
}

 

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值