当前位置: 代码迷 >> 综合 >> 2020牛客暑期多校训练营(第二场)Cover the Tree
  详细解决方案

2020牛客暑期多校训练营(第二场)Cover the Tree

热度:70   发布时间:2024-01-28 01:10:24.0

Cover the Tree

题目大意
给定一个无根树,你需要选择最少数量的链,使得树上的所有边都被至少一条链覆盖。输出最少数量,和对应的解。如果有多解,输出任意一个即可。**
输入:
第一行:n (1≤n≤2×10^5)
接下来n-1行每行包含两个整数u,v(1 ≤u < v ≤n)表示节点u和v之间有一条双向边
输出:
第一行输出一个整数k,表示覆盖所有边的最少链数
接下来k行输出两个数u,v,表示节点u和v之间有一条链
样例输入:

5
1 2
1 3
2 4
2 5

样例输出:

2
2 3
4 5

用类似于DFS序的方法将每个叶子节点编号,求出叶子结点个数ans,链的条数就是ans/2向上取整,考虑到每一条边都要被链覆盖,所以第i个叶子节点需要和第ans/2+i个叶子节点相匹配
代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e6+5;
vector<int> vec[MAXN];
int n,u,v,ans,a[MAXN];
void dfs(int x,int fa)
{if(vec[x].size()==1) a[++ans]=x;for(int i=0;i<vec[x].size();i++){int y=vec[x][i];if(y==fa) continue;dfs(y,x);}
}//求叶子节点的数量和顺序
int main()
{scanf("%d",&n);for(int i=1;i<n;i++){scanf("%d%d",&u,&v);vec[u].push_back(v);vec[v].push_back(u);}if(n==2) printf("1\n%d %d\n",u,v);for(int i=1;i<=n;i++)if(vec[i].size()>1){dfs(i,-1);break;}printf("%d\n",(ans+1)/2);for(int i=1;i<=(ans+1)/2;i++)printf("%d %d\n",a[i],a[i+ans/2]);
}
  相关解决方案