标签:img eve alt code 存在 show continue print bsp
题目链接:https://vjudge.net/problem/UVA-1267
首先我们要把这样一棵无根树转换成有根树,那么树根我们可以直接使用$VOD$。
还有一个性质:如果深度为$d$的一个节点并不能被覆盖,那么我们在它的第$k$级的祖先(父亲为第一级)那里建一个$VOD$是最优的,其实很好证明它不仅能覆盖这些点,还能覆盖更多的点。
思路:
1.进行第一遍dfs,将无根树变成有根树。在建树的过程中用$node[d][i](d>k)$表示第$d$层有不能被覆盖到的点,那么可以避开“按深度排序”这个过程。然后对于$d\leq k$的情况我们直接当它不存在。
2.从$n-1$层倒着遍历,如果有点不能被覆盖到,那么就找它的$k$级祖先,在那里设上$VOD$,然后进行更新。
注意:
1.只需处理叶节点。 2.$u$和$father$之间是无向边!
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 8 const int maxn=1010; 9 vector<int> g[maxn],node[maxn]; 10 int n,s,k,fa[maxn]; 11 bool vis[maxn]; 12 13 void dfs(int u,int f,int d){ 14 fa[u]=f; 15 int nc=g[u].size(); 16 if(nc==1&&d>k) node[d].push_back(u); 17 for(int i=0;i<nc;i++){ 18 int v=g[u][i]; 19 if(v!=f) dfs(v,u,d+1); 20 } 21 } 22 23 void dfs2(int u,int f,int d){ 24 vis[u]=1; 25 int nc=g[u].size(); 26 for(int i=0;i<nc;i++){ 27 int v=g[u][i]; 28 if(v!=f&&d<k) dfs2(v,u,d+1); 29 } 30 } 31 32 int solve(){ 33 int ans=0; 34 memset(vis,0,sizeof(vis)); 35 for(int d=n-1;d>k;d--){ 36 for(int i=0;i<node[d].size();i++){ 37 int u=node[d][i]; 38 if(vis[u]) continue; 39 int v=u; 40 for(int j=0;j<k;j++) v=fa[v]; 41 dfs2(v,-1,0); 42 ans++; 43 } 44 } 45 return ans; 46 } 47 48 int main(){ 49 int T; 50 scanf("%d",&T); 51 while(T--){ 52 scanf("%d%d%d",&n,&s,&k); 53 for(int i=1;i<=n;i++){ 54 g[i].clear(); 55 node[i].clear(); 56 } 57 for(int i=0;i<n-1;i++){ 58 int a,b; 59 scanf("%d%d",&a,&b); 60 g[a].push_back(b); 61 g[b].push_back(a); 62 } 63 dfs(s,-1,0); 64 printf("%d\n",solve()); 65 } 66 return 0; 67 }
标签:img eve alt code 存在 show continue print bsp
原文地址:https://www.cnblogs.com/New-ljx/p/12305601.html