2020牛客多校第二场C题Cover the Tree(dfs构造)
题目链接 https://ac.nowcoder.com/acm/contest/5667/C
题意:给你一个无根树,任意选两点进行覆盖,要求所有点边都被覆盖,求最少选多少对,也要输出是怎么样的对
题解:我们很容易想到是用叶子节点去覆盖,所以我们用dfs将一颗无根树转化为有根的,而且根的节点的度最好不为1,比赛wa自闭。
然后是进行构造如果叶子节点的数量是奇数,我们发现还有一些点边是未覆盖的,所以我们要加一个与根节点相连
如果是叶子节点的数量是偶数,我们以前面一半后后一半进行构造,比赛时我用的第一个与最后一个构造,到中间时会有两个点是同一个父亲而父亲上面的点未覆盖,再一次自闭....
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }