2020牛客暑期多校训练营Cover the Tree(构造,dfs序)

   日期:2020-07-17     浏览:86    评论:0    
核心提示:题目描述Given an unrooted tree, you should choose the minimum number of chains that all edges in the tree are covered by at least one chain. Print the minimum number and one solution. If there are multiple solutions, print any of them.输入描述:The first line co_c

Cover the Tree

题目描述

输入描述:

输出描述:

示例1

输入

5
1 2
1 3
2 4
2 5

输出

2
2 3
4 5

说明

题目大意

给定一个k个节点的无根树,求最少的链覆盖树上的所有边。并输出覆盖方式(链的两边的节点编号)(SPJ)。

分析

一看就想到和叶节点有关。由于每个叶节点一定要覆盖到,则若有n个叶节点,则必要n/2向上取整的链才能覆盖到所有叶节点,并且这些链可以同时覆盖其他边。
于是,链的数量就求出来了,重点是覆盖的策略。一开始写的好像可以hack掉

覆盖策略

先用dfs序将每个叶节点编号,然后以ans/2为界,一一对应做链即可。经过长期实验+数百次WA+官方题解易得

代码

#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
using namespace std;
const int MAXN=2e5+100;
vector<int> vec[MAXN];
int a[MAXN],num;
void dfs(int pos,int fa){
	if(vec[pos].size()==1){
		a[++num]=pos;return;
	}//size==1的就是叶节点,依照此顺序存到数组中
	for(int i=0;i<vec[pos].size();i++){
		int s=vec[pos][i];
		if(s==fa) continue;
		dfs(s,pos);
	}
}
int main()
{
    int k,u,v;
    scanf("%d",&k);
    for(int i=1;i<k;i++){
        scanf("%d%d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    if(k==2){
    	printf("1\n");
    	printf("%d %d\n",u,v);return 0;
	}
    for(int i=1;i<=k;i++)
    	if(vec[i].size()>1){
    		dfs(i,-1);break;
    		//无根树因此需要找一个root做dfs
		}
    printf("%d\n",(num+1)/2);//答案即为叶节点个数一半ceil
    for(int i=1;i<=(num+1)/2;i++){
        int x=a[i],y=a[i+num/2];
        printf("%d %d\n",x,y);
    }//按上述策略输出
}

END

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服