【算法学习笔记】41.并查集 SJTU OJ 1283 Mixture
2015-05-01 19:52
357 查看
---恢复内容开始---
现在CC有n种液体,其中m对会发生反应,现在她想把这n种液体按某种顺序倒入一个容器内,让她获得最刺激的体验,使危险系数尽量大。
我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1。每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变。
请你求出把这n种液体倒在一起的最大危险系数。
接下来m行,每行两个数a, b。表示a号液体和b号液体会发生反应。保证同一种边不重复出现。
30%的数据: \( 1 \le n \le 10 \)
100%的数据: \( 1 \le n \le 1000 \)
数学上的本质是:
给定n个点,m个边,求出有多少个独立的连通块k
输出2^(n-k)
注意高精度........
对于这个问题, 可以想到先把每个点都当做一个独立的块,然后每输入一条边,我们就做出相应的更新 , 从而最后可以分成k个独立块
但是不能用图来存储,因为图的存储量太大,而且耗时.想到我们的目标只是要算出独立块的个数,可以利用集合的思想来完成这件事
这种数据结构叫做 并查集 Union Find
顾名思义有合并的过程 有查找的过程
理解的来源是:http://blog.csdn.net/dellaserss/article/details/7724401
这个博主简直太逗...
SJTU OJ的代码如下 [/code]
View Code
Description
CC非常喜欢化学,并且特别喜欢把一大堆液体倒在一起。现在CC有n种液体,其中m对会发生反应,现在她想把这n种液体按某种顺序倒入一个容器内,让她获得最刺激的体验,使危险系数尽量大。
我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1。每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变。
请你求出把这n种液体倒在一起的最大危险系数。
Input Format
第一行为两个数n和m。接下来m行,每行两个数a, b。表示a号液体和b号液体会发生反应。保证同一种边不重复出现。
30%的数据: \( 1 \le n \le 10 \)
100%的数据: \( 1 \le n \le 1000 \)
Output Format
一行,即最大危险系数。Sample Input
3 2 1 2 2 3
Sample Output
4
数学上的本质是:
给定n个点,m个边,求出有多少个独立的连通块k
输出2^(n-k)
注意高精度........
对于这个问题, 可以想到先把每个点都当做一个独立的块,然后每输入一条边,我们就做出相应的更新 , 从而最后可以分成k个独立块
但是不能用图来存储,因为图的存储量太大,而且耗时.想到我们的目标只是要算出独立块的个数,可以利用集合的思想来完成这件事
这种数据结构叫做 并查集 Union Find
顾名思义有合并的过程 有查找的过程
理解的来源是:http://blog.csdn.net/dellaserss/article/details/7724401
这个博主简直太逗...
SJTU OJ的代码如下 [/code]
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; int prenode[1050]; int num[350]={0}; int len = 1; //2次的power方 void mul2(int power){ num[0]=1; for (int i = 0; i < power; ++i) { int r = 0; int ori_len = len; for (int j = 0; j < ori_len ; ++j) { int tmp = num[j]*2 + r; r = 0; num[j] = ( tmp ) % 10; // cout<<num[j]<<endl; if(tmp >= 10){ r = (tmp)/10 ;//, num[len++]=r; } } if(r!=0) num[len++] = r; } } //查 int find(int x){//查找到x所在的子图的根节点 int res = x; while(res != prenode[res] ){//res是根节点的条件是 res的根节点是本身 res = prenode[res]; } //压缩路径 让此次查询中的所有涉及的节点的上级节点都是根节点 从而尽量形成只有二级的树结构(不能保证一定是 和输入的边顺序有关) while(x != res){ int pre = prenode[x]; prenode[x] = res; x = pre; } return res; } //并 void join(int x, int y){//把 x 和 y 并到同一子图中 int rootx = find(x) , rooty = find(y); if(rootx != rooty)//x,y不属于同一子图时才有并的必要 prenode[rootx] = rooty;//属于同一子图 return; } int main(int argc, char const *argv[]) { int n,m; cin>>n>>m; //初始化n个点 根节点为自身 for (int i = 1; i <= n; ++i) prenode[i] = i; //调整每个边 for (int i = 0; i < m; ++i) { int x,y; cin>>x>>y; join(x,y); } //找连通区域的个数k int k = 0; for (int i = 1; i <= n; ++i) if(prenode[i]==i) k++; //cout<<k<<endl; //cout<<( 1<<(n-k) )<<endl; mul2(n-k); for (int i = len-1; i >=0; --i) { cout<<num[i]; }cout<<endl; return 0; }
View Code
相关文章推荐
- 【算法学习笔记】62.状态压缩 DP SJTU OJ 1088 邮递员小F
- 【算法学习笔记】85.破环为链 序列DP 松弛+代价 SJTU OJ 1073 能量项链
- 【算法学习笔记】42.正反DP 填充问题 SJTU OJ 1285 时晴时雨
- 【算法学习笔记】82.素数生成 数据范围利用 SJTU OJ 1020 分解质因数
- 【算法学习笔记】63. BFS SJTU OJ 1281 蹦蹦跳跳
- 【算法学习笔记】51. 贪心法 区间排序问题 SJTU OJ 1360 偶像丁姐的烦恼
- 【算法学习笔记】36.凸包 求最大两点距离 SJTU OJ 1244 Date A Live
- 【算法学习笔记】48.递归/显式栈 SJTU OJ 1358 分割树
- 【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
- 【算法学习笔记】60.经典动态规划 SJTU OJ 1370 赫萝的桃子
- 【算法学习笔记】56.区间合并问题变形 SJTU OJ 1365 最少道路
- 【算法学习笔记】83.排序辅助 动态规划 SJTU OJ 1282 修路
- 【算法学习笔记】52.一道题的三种方法..二分答案、动态规划、计算几何 SJTU OJ 1250 BestSubsequence
- 【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
- 【算法学习笔记】86.栈 中缀表达式 SJTU OJ 1033 表达式计算
- 【算法学习笔记】33.在线算法 SJTU OJ 1006 求和游戏
- 【算法学习笔记】64. 枚举法 SJTU OJ 1381 畅畅的牙签
- 【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
- 【算法学习笔记】24.记忆化搜索 解题报告 SJTU OJ 1002 二哥种花生
- 【算法学习笔记】55.DFS 记忆化搜索 SJTU OJ 1063 小M爱滑雪