《算法竞赛-训练指南》第一章-1.15_LA 3902
来源:互联网 发布:诺基亚e71软件下载 编辑:程序博客网 时间:2024/06/07 21:02
这道题目我真的有点泪奔了!
写了整整一下午才A掉,这是一道比较考察综合知识的题目,要求你对DFS,要求你对模型的建立,要求你对图的掌握要非常熟练。如果是不熟练的话,你是写不出来的。
这个题目的意思是,给你N个结点,代表着客户端和服务端,客户端仅为这个无根树的叶结点时,其余的就是服务端了,但是有一个是发射信号的最终客户端,就要求着,如果有客户端距离服务端太远(距离超过所要求的K)的话,就无法正确的接受到信号了,所以就要重新再建立一个服务端了。题目要求求出需要建立的最少的服务端。
做题的步骤应该是这样的:首先将无根树转化成有根树,无根树转化成有根数的算法就是DFS,将所有的结点搜到,搜索的时候一定要记住要把结点的关系转化成功,也就是,将结点和结点所对应的父亲存好。
这个过程中, DFS能得意进行下去的条件也是至关重要的。if (v != f)也就是不能让他回搜。形成循环,所有的这样双向图都应该是这样判断的。
(中间啊有个小插曲,就是我突然就想看看自己到底打字用几个手指头了,才用了七个,还有三个没有用到啊)
这个还有个很好的知识点,就是将所有待解决的结点,按照深度的不同另外存储起来,然后遍历所有的可能的深度,就可以求出解,当然求可能的时候要求最优解。也就是求距离叶结点最大可满足距离的那个结点。然后循着这个结点DFS所有的叶子结点,标记就行了。
非常的不好意思,为了看自己到底使用几个手指头打字,我发现现在自己都不能好好的打字了,所有有点写的言不达意,很抱歉啊。
贴出代码,我要适应一下正确的打字方法:
#include <stdio.h>#include <string.h>#include <iostream>#include <vector>#include <string>using namespace std;const int MAXN = 1022;int N;int root;int K;int a, b;vector <int> G[MAXN], node[MAXN];int father[MAXN];int vis[MAXN];void converse(int v, int f, int d){father[v] = f;int cnt = G[v].size();if (d > K && cnt == 1) //如果这个服务器已经覆盖不到了,而且也是个叶子节点,那么先把它存起来. { node[d].push_back(v);}for (int i = 0; i < cnt; i++){int t = G[v][i];if (t != f) //这里是t!=f????我要去死!!! {converse(t, v, d + 1);}}}void DFS(int v, int f, int d){if (d > K){return ;}int nc = G[v].size();if (nc == 1 && d <= K){vis[v] = 1;return ;}for (int i = 0; i < nc; i++){int t = G[v][i];if (t != f){DFS(t, v, d + 1);}}}/*void DFS(int u, int f, int d){vis[u] = 1;int nc = G[u].size();for (int i = 0; i < nc; i++){int v = G[u][i];if (v != f && d < K){DFS(v, u, d + 1);}}}*/int solve(){int cnt = 0;memset(vis, 0, sizeof(vis));for (int i = N - 1; i > K; i--){int nc = node[i].size(); //遍历那些没有覆盖的点,从深处开始. for (int j = 0; j < nc; j++){int v = node[i][j];if (!vis[v]){for (int k = 0; k < K; k++){v = father[v];}DFS(v, -1, 0);cnt++;}} }return cnt;}void init(){memset(father, 0, sizeof(father));for (int i = 1; i <= N; i++) //我都想死了!!!!这初始化!!!~~~我真!! {G[i].clear();node[i].clear();}}int main(){int T;scanf("%d", &T);while (T--){scanf("%d", &N);scanf("%d%d", &root, &K);init();for (int i = 0; i < (N - 1); i++) //这里使用的是邻接表建图,因为数据量实在是不小1000; {scanf("%d%d", &a, &b);G[a].push_back(b);G[b].push_back(a);}converse(root, -1, 0);int ans = solve();printf("%d\n", ans);}//system("pause");return 0;}
- 《算法竞赛-训练指南》第一章-1.15_LA 3902
- 《算法竞赛-训练指南》第一章-1.4_LA 3708
- 《算法竞赛-训练指南》第一章-1.12_LA 3971
- 《算法竞赛-训练指南》第一章-1.13_LA 3635
- 《算法竞赛-训练指南》第一章-1.16_LA 3177
- 《算法竞赛-训练指南》第一章-1.20_LA 3905
- 《算法竞赛-训练指南》第一章-1.22_LA 3209
- 《算法竞赛-训练指南》第一章-1.23_LA 3695
- 《算法竞赛-训练指南》第一章-1.26_LA 3882
- 《算法竞赛-训练指南》第二章-2.12_LA 5059
- 《算法竞赛-训练指南》第二章-2.27_LA 5009
- 《算法竞赛-训练指南》第一章-1.21_LA2678
- 《算法竞赛-训练指南》第二章-2.28_LA 3485(simpson)
- 《算法竞赛-训练指南》第三章-3.6_LA 3027(并查集)
- 《算法竞赛-训练指南》第三章-3.7_LA 3429(树状数组)
- 《算法竞赛入门经典——训练指南》第一章相关内容
- 《算法竞赛入门经典——训练指南》第一章相关内容
- 《算法竞赛-训练指南》第一章-1.5_UVa 10881
- Ubuntu 12.04搭建hadoop单机版环境
- 用正则表达式获取网页的email
- 递归的一些简单的例子,供大家参考
- csapp2e 家庭作业 6.39
- 实时数据库简介
- 《算法竞赛-训练指南》第一章-1.15_LA 3902
- ARM Uboot经历——Uboot地址问题
- 有关时间戳
- hdu1263 水果(结构体排序)
- csapp2e 家庭作业 6.40
- AndroidStudio如何导入Eclipse中的Android项目
- IDENTITY_INSERT 设置OFF 不能插入列标识符解决办法
- 视觉直观感受7种常用的排序算法
- Cocos2D-iphone 开发之 设置屏幕方向(Interface Orientation)