传送门
题意:给你一个n个点,m条边的无向图(保证两个有一条路连通),现在要求你利用这些边生成一个棵树,保证结点1的度为k。
思路:我们要满足1的度为k,如果连接1边的数量小于 k ,那么答案肯定是 NO。如果连接 1 边的数量大于 k 我们肯定要删除多余的边,但是把边删除过后,我们还要保证剩余的边还能生成一棵树。我们要判断不是通过1结点来连接的点集有多少个,其实就是先把1连接的边去掉,判断剩下的强连通分量的个数(可以用tanjan,也可以用并查集)。如果强连通分量的个数>k,则说明满足1的度为k,但是又无法生成一个树。否则,答案就存在,我们先保证1能够和所有强连通分量连接,然后满足1的度为k,最后通过BFS来获得一棵树。
附上代码:
///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const int INF=0x3f3f3f3f;
int n,m,k;
int vis[200005];
struct node
{
int e;
int p;
}load[400005];
int head[200005],sign;
vector<int>q;
void add_edge(int s,int e)
{
load[++sign]=node{e,head[s]};
head[s]=sign;
}
int dfn[200005],low[200005],time;
int stack_[200005],inque[200005],top;
int belong[200005],cnt;
void tanjan(int s)
{
dfn[s]=low[s]=++time;
stack_[++top]=s;
inque[s]=1;
for(int i=head[s];i!=-1;i=load[i].p)
{
int e=load[i].e;
if(!dfn[e])
{
tanjan(e);
low[s]=min(low[s],low[e]);
}
else
{
if(inque[e])
low[s]=min(low[s],dfn[e]);
}
}
int t;
if(dfn[s]==low[s])
{
cnt++;
do
{
t=stack_[top--];
inque[t]=0;
belong[t]=cnt;
}while(t!=s);
}
}
void bfs()
{
memset(vis,0,sizeof(vis));
vis[1]=1;
queue<int>w;
w.push(1);
while(!w.empty())
{
int s=w.front();
w.pop();
for(int i=head[s];i!=-1;i=load[i].p)
{
int e=load[i].e;
if(!vis[e])
{
printf("%d %d\n",s,e);
w.push(e);
vis[e]=1;
}
}
}
}
void init()
{
sign=time=top=cnt=0;
for(int i=1;i<=n;i++)
{
head[i]=-1;
dfn[i]=low[i]=0;
vis[i]=0;
}
}
int main()
{
int s,e;
scanf("%d %d %d",&n,&m,&k);
init();
while(m--)
{
scanf("%d %d",&s,&e);
if(s!=1&&e!=1) ///先去掉1连接的边
{
add_edge(s,e);
add_edge(e,s);
}
else
q.push_back(max(s,e));
}
///求强连通分量的个数
for(int i=2;i<=n;i++)
{
if(!dfn[i])
tanjan(i);
}
///不能够生成一棵树
if(cnt>k||q.size()<k)
printf("NO\n");
else
{
int d=q.size();
for(int i=0;i<d;i++)///先满足所有强连通分量和1相连
{
e=q[i];
if(!vis[belong[e]])
{
vis[belong[e]]=1;
add_edge(1,e);
add_edge(e,1);
q[i]=-1;
k--;
}
}
if(k)///满足1的度为k的要求
{
for(int i=0;i<d&&k;i++)
{
if(q[i]!=-1)
{
add_edge(q[i],1);
add_edge(1,q[i]);
k--;
}
}
}
printf("YES\n");
bfs();///生成一棵树
}
}