C Cover the Tree(选链覆盖树)
题:https://ac.nowcoder.com/acm/contest/5667/C
题意:选最少数量的“链”来覆盖整颗树,使树的每条边都至少被覆盖一次
分析:关键是理解证明过程:
:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define pb push_back #define MP make_pair typedef long long ll; const int mod=1e9+7; const int M=2e5+5; const int inf=0x3f3f3f3f; const ll INF=1e18; vector<int>g[M]; int a[M],du[M],dfn[M],cnt; void dfs(int u,int fa){ dfn[u]=++cnt; for(auto v:g[u]) if(v!=fa) dfs(v,u); } int main(){ int n; scanf("%d",&n); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); g[u].pb(v); g[v].pb(u); du[u]++,du[v]++; } if(n==1) return puts("0"),0; else if(n==2) return printf("1\n%1 2"),0; int tot=0,rt=1; for(int i=1;i<=n;i++) if(du[i]==1) a[tot++]=i; else rt=i; dfs(rt,0); sort(a,a+tot,[&](int x,int y){ return dfn[x]<dfn[y]; }); int tmp=tot/2; if(tot&1){ printf("%d\n",tmp+1); printf("%d %d\n",rt,a[tot-1]); } else printf("%d\n",tmp); for(int i=0;i<tmp;i++) printf("%d %d\n",a[i],a[i+tmp]); return 0; } /** 8 1 2 2 3 3 4 3 5 1 7 7 6 7 8 */