UVA 1267 Network(DFS)

题目链接: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 }

AC代码

 

相关文章