UVA 1267 Network(DFS)

题目链接:https://vjudge.net/problem/UVA-1267

首先我们要把这样一棵无根树转换成有根树,那么树根我们可以直接使用$VOD$。

还有一个性质:如果深度为$d$的一个节点并不能被覆盖,那么我们在它的第$k$级的祖先(父亲为第一级)那里建一个$VOD$是最优的,其实很好证明它不仅能覆盖这些点,还能覆盖更多的点。

思路:

1.进行第一遍dfs,将无根树变成有根树。在建树的过程中用$node[d][i](d>k)$表示第$d$层有不能被覆盖到的点,那么可以避开“按深度排序”这个过程。然后对于$dleq 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
",solve());
65     } 
66     return 0;
67 }
AC代码
原文地址:https://www.cnblogs.com/New-ljx/p/12305601.html