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


题目地址

题目

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 contains one integer(1≤n≤2×10 5),denoting the size of the tree.Following n−1 lines each contains two integers u,v (1≤u<v≤n), denoting an edge in the tree.It’s guaranteed that the given graph forms a tree.

输出描述

The first line contains one integer k, denoting the minimum number of chains to cover all edges.
Following k lines each contains two integers u,v (1≤u,v≤n), denoting a chain you have chosen. Here u=v is permitted, which covers no edge.

样例输入

5
1 2
1 3
2 4
2 5

样例输出

2
2 3
4 5

说明

在这里插入图片描述

题目大意

给定一个无根树,选择树中所有边至少被一条链覆盖的最小链数。输出最小数字和其中任何一个解决方案。

解题思路

寻找不相邻的叶子节点,匹配输出。如下图(官方题解)
在这里插入图片描述
本题难点在于使叶子节点不相邻,如图
图1
选择(4,5)(6,7)和(4,6)(5,7)结果是不同的
(4,5)(6,7)
(4,6)(5,7)
可以发现(4,6)(5,7)合法,可是(4,5)(6,7)不合法。
此时我们可以用dfs判断在哪一个子树来求解。

AC但不是正解的代码

(可能是数据太水了)

#include<bits/stdc++.h>
using namespace std;
int n,u,v,a[202020],ans,w,sum[202020];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++){scanf("%d%d",&u,&v);a[u]++,a[v]++;}
    for(int i=1;i<=n;i++)if(a[i]==1){ans++;sum[ans]=i;}
    printf("%d\n",(ans+1)/2);//
    for(int i=1;i<=(ans+1)/2;i++)printf("%d %d\n",sum[i],sum[i+ans/2]);
}

AC正解

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+100;
int k,ans,u,v,root=-1,flag=1,a[MAXN],du[MAXN];
vector<int> vec[MAXN];
void DFS(int x,int fx)
{
    if(du[x]==1)
    {
        a[++ans]=x;return;
    }
    for(int i=0;i<vec[x].size();i++)
    {
        int now=vec[x][i];
        if(now==fx) continue;
        DFS(now,x);
    }
}
int main()
{
    scanf("%d",&k);
    for(int i=1;i<k;i++)
    {
        scanf("%d%d",&u,&v);
        du[u]++;du[v]++;
        if(du[u]>=2&&flag) root=u,flag=0;
        if(du[v]>=2&&flag) root=v,flag=0;
        vec[u].push_back(v);vec[v].push_back(u);
    }
    if(root==-1)
    {
        printf("1\n%d %d",u,v);return 0;
    }
    DFS(root,-1e9);
    printf("%d\n",(ans+1)/2);
    for(int i=1;i<=ans/2;i++) printf("%d %d\n",a[i],a[(ans+1)/2+i]);
    if(ans&1) printf("%d %d\n",root,a[ans/2+1]);
}

猜你喜欢

转载自blog.csdn.net/cxkdad/article/details/107338269
今日推荐