1. 程式人生 > 實用技巧 >2020牛客多校第二場C題Cover the Tree(dfs構造)

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