2020牛客暑期多校訓練營(第二場) [Cover the Tree]
阿新 • • 發佈:2020-07-13
題目大意:
給一棵樹,求最少的鏈使得所有的邊至少被一條鏈覆蓋,輸出任意一種方案。
題解:
這個題目就是對於節點 \(i\) ,要不就是從下面找一個葉子節點,要不就是2個葉子節點,反正至少要一個節點,如此才能把 \(i\) 節點到 \(i\) 節點的父親這條邊覆蓋。按照這個想法去寫這個題目即可。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <algorithm> #include <iostream> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 2e5+2; typedef long long ll; vector<int>G[maxn]; int num[maxn],l[maxn],r[maxn]; void add(int u,int v){ G[u].push_back(v); G[v].push_back(u); } int ans[maxn]; void dfs(int u,int pre){ int res=0; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==pre) continue; dfs(v,u); res++; } if(!res) { num[u]=1,l[u]=u; return ; } num[u]=0; l[u]=r[u]=0; for(int i=0;i<G[u].size();i++){ int v = G[u][i]; if(v==pre) continue; if(num[v]==1) { if(num[u]==0) num[u]=1,l[u]=l[v]; else if(num[u]==1) num[u]=2,r[u]=l[v]; else num[u]=1,ans[r[u]]=l[v]; } else { if(num[u]==0) num[u]=2,l[u]=l[v],r[u]=r[v]; else if(num[u]==1) num[u]=1,ans[l[u]]=r[v],l[u]=l[v]; else num[u]=2,ans[l[u]]=r[v],l[u]=l[v]; } } if(u==1){ if(res==1) ans[l[u]]=1,ans[r[u]]=1; else ans[l[u]]=r[u]; } } int main(){ int n; scanf("%d",&n); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); } dfs(1,0); int now=0; for(int i=1;i<=n;i++){ if(ans[i]) now++; } printf("%d\n",now); for(int i=1;i<=n;i++){ if(ans[i]) printf("%d %d\n",i,ans[i]); } return 0; }