Tree - NHIP第三题解题报告 - 并查集入门练习
2016-02-15 19:34
323 查看
这题的意义不用多说,关键就是数据都很大,而且要理解好树的意义,只需用并查集统计边数与点数,最后再用循环来看一遍就行了。这题的难度不大,但当时我却用了广搜来做,严重超时,只有并查集才足够高效。
#include <cstdio> using namespace std; struct node { int link; int point_num; int line_num; bool haveFind; }; node point[1000001]; int find_root(int t) { int root,lt; root=t-1; //查找 while(point[root].link!=root) { root=point[root].link; } //并查集的路径优化 while(point[t-1].link!=root) { lt=point[t-1].link; //存储当前点的父亲 point[t-1].link=root; //将当前点设置为直接指向Root t=lt+1; //将当前点的父亲赋回给循环变量 } return root; } inline void union_set(int f,int s) { point[ find_root( s ) ].point_num+=point[ find_root( f ) ].point_num; point[ find_root( s ) ].line_num+=point[ find_root( f ) ].line_num+1; point[ find_root( f ) ].link = find_root( s ); } int main() { int n; int m; scanf("%d %d",&n,&m); //建立整个并查集的结构 for (int i=0; i<n; ++i) { point[i].link=i; point[i].point_num=1; point[i].line_num=0; point[i].haveFind=false; } int f,s; //建立并查集的关系 for (int i=0; i<m; ++i) { scanf("%d %d",&f,&s); //合并两个图 if (find_root(f)!=find_root(s)) { union_set(f,s); } } long long int ans = 0; for (int i=0; i<n; ++i) { printf("%d",find_root(i)); if ((point[find_root(i)].point_num-1 == point[find_root(i)].line_num) && !point[find_root(i)].haveFind) { //是否是树,是否访问过 point[find_root(i)].haveFind=true; //设为访问过 ++ans; //累计答案 } } printf("%d",ans); //输出答案 return 0; }
相关文章推荐
- NHIP(2015)解题报告(第3题)
- IOS引入第三方冲突解决办法
- iOS在线音频播放FreeStreamer
- hdoj5247找连续数【rmq】
- iOS之@selector的函数传递多个参数
- linux下redis安装
- c#里,WebBrowser实现不加载图片等控制
- c#值类型与引用类型,可空类型
- iOS之iOS键盘隐藏
- c语言:用8个2*1的小矩形横着或竖着无重叠地覆盖一个2*8的大矩形,总共有多少种方法?
- 种树郭橐驼传
- 【解决】SOUI向导生成项目(VC2013以上版本编译时)无法运行XP解决
- hdoj5249KPI【set】
- iOS之iOS键盘隐藏
- iframe根据内容自适应高度
- SharedPreferences 用法总结
- android 5.0及以上https No peer certificate
- hdoj5248序列变换【二分】
- 整体二分小结
- java多线程 并发 编程