2020牛客多校第二场C题Cover the Tree(dfs构造)

题目链接 https://ac.nowcoder.com/acm/contest/5667/C

题意:给你一个无根树,任意选两点进行覆盖,要求所有点边都被覆盖,求最少选多少对,也要输出是怎么样的对

题解:我们很容易想到是用叶子节点去覆盖,所以我们用dfs将一颗无根树转化为有根的,而且根的节点的度最好不为1,比赛wa自闭。

然后是进行构造如果叶子节点的数量是奇数,我们发现还有一些点边是未覆盖的,所以我们要加一个与根节点相连

如果是叶子节点的数量是偶数,我们以前面一半后后一半进行构造,比赛时我用的第一个与最后一个构造,到中间时会有两个点是同一个父亲而父亲上面的点未覆盖,再一次自闭....

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;

vector<int> G[maxn]; 
vector< int >ans;
int n, root, p[maxn],indexx[maxn];

void dfs(int u, int fa) //递归转化以U为根的子树, U的父亲为fa 
{
    int d = G[u].size();
//    if(d==1) ans.push_back(u);
      int flag=0;
    for(int i = 0; i < d; i++) {
        const int& v = G[u][i];
        if(v != fa) {
            flag=1;
            dfs(v, p[v] = u);
            
        }
    }
    if(!flag){
        ans.push_back(u);
    }
}            

int main()
{
    int u, v;
    scanf("%d", &n);
    for(int i = 0; i < n-1; ++i)
    {
        scanf("%d %d", &u, &v);
        if(u==v) continue;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i=1;i<=n;i++){
        if(G[i].size()!=1){
            root=i;
            break;
        }
    }
    //root=1;
    //cout<<root<<endl;
    p[root] = -1;
    dfs(root, -1);
//    for(int i = 2; i <=n; ++i) {
//        printf("p[%d] = %d\n", i, p[i]);
//    }

//    for(int i=0;i<ans.size();i++){
//        cout<<ans[i] <<" " <<index [ans[i]]<<endl;
//        
//    }
//    sort(ans.begin(),ans.end());
//    int d=ans.size();
//    int t=(d+1)/2;
//    printf("%d\n",t);
//    if( d%2==0){
//        for(int i=0;i<t;i++){
//            printf("%d %d\n",ans[i].second,ans[d-i-1].second);
//        }
//    }else{
//        int i;
//        for(i=0;i<t-1;i++){
//            printf("%d %d\n",ans[i].second,ans[d-i-1].second);
//        }
//        printf("%d %d\n",root,ans[t-1].second);
//    } 
    int len=ans.size();
    if(len& 1){
        len++;
        ans.push_back(root);
    }
    len/=2;
    printf("%d\n",len);
    for(int i=0;i<ans.size();i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
    for(int i=0;i<len;i++){
        printf("%d %d\n",ans[i],ans[len+i]);
    }
    return 0;
}  
View Code

 

posted @ 2020-08-01 20:25  杰瑞与汤姆  阅读(161)  评论(0编辑  收藏  举报