并查集部分题目
来源:互联网 发布:香港天文台软件 编辑:程序博客网 时间:2024/04/29 18:21
1 hdu 1232 题目网址
题意:实现任意两个城镇有道路相通,已经修建部分道路,问至少还需修建多少条道路。
思路:连通分量的个数-1
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;const int maxn = 1000 ;int fa[maxn] , t[maxn] ;int Find(int x){ while(x != fa[x]) { fa[x] = fa[fa[x]] ; x = fa[x] ; } return x ;}void Union(int x , int y){ int fx = Find(x) ; int fy = Find(y) ; if(fx != fy) fa[fy] = fx ;}int main(){ int N , M , a, b; while(scanf("%d" , &N)!= EOF &&N) { scanf("%d" , &M) ; for(int i = 1 ; i <= N ; i ++) fa[i] = i ; for(int i =0 ; i < M ; i++) { scanf("%d%d" , &a ,&b) ; Union(a ,b) ; } memset(t , 0 , sizeof(t) ) ; for(int i = 1 ; i <= N ; i++) t[Find(i)] = 1 ; int ans = 0 ; for(int i = 1 ; i <= N ; i++) if(t[i]) ans++ ; printf("%d\n" , ans - 1) ; } return 0;}
hdu 1213 题目网址
题意: 有n个人, 每一桌上的人都相互认识(认识关系可传递),至少需要多少桌可使所有人都坐下
思路:求连通分量数
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;const int maxn = 1000 ;int fa[maxn] , t[maxn] ;int Find(int x){ while(x != fa[x]) { fa[x] = fa[fa[x]] ; x = fa[x] ; } return x ;}void Union(int x , int y){ int fx = Find(x) ; int fy = Find(y) ; if(fx != fy) fa[fy] = fx ;}int main(){ int T , N , M , a , b; scanf("%d" , &T) ; for(int i = 1 ; i <= T ; i++) { scanf("%d%d" , &N, &M) ; for(int i = 1 ; i <= N ; i++) fa[i] = i ; while(M --) { scanf("%d%d" , &a, &b) ; Union(a, b) ; } memset(t , 0 , sizeof(t)) ; for(int i = 1 ; i <= N ; i++) t[Find(i)] = 1 ; int ans = 0 ; for(int i = 1 ; i <= N ; i++) if(t[i]) ans ++ ; printf("%d\n" ,ans) ; } return 0 ;}
hdu 1598 题目链接
题意:XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的“舒适度”有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ),
但XX星人对时间却没那么多要求。要你找出一条城市间的最舒适的路径。(SARS是双向的)。
思路:贪心+并查集,对所有道路按照速度进行排序,不断添加道路,当a , b连通时,取道路速度差的最小值。
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define Min(a,b) ( (a) < (b) ? (a) : (b) )const int maxn = 1005 , inf = 1e9;int fa[205] , n , MIN;struct Edge{ int s , t ; int speed ;};bool cmp(Edge a , Edge b){ return a.speed < b.speed ;}Edge e[maxn] ;void init(int n){ for(int i =1 ; i <= n ; i ++) fa[i] = i ;}int Find(int a){ while(a != fa[a]) { fa[a] = fa[fa[a]] ; a = fa[a] ; } return a ;}void Union(int x ,int y){ int fx = Find(x) ; int fy = Find(y) ; if(fx != fy) fa[fy] = fx ;}int main(){ int m , a ,b ,q ; while(scanf("%d%d" , &n ,&m) != EOF) { for(int i = 0 ; i < m ; i++) scanf("%d%d%d" , &e[i].s , &e[i].t , &e[i].speed) ; sort(e , e + m , cmp) ; scanf("%d" , &q) ; while(q--) { scanf("%d%d" , &a, &b) ; MIN = inf ; for(int i = 0; i < m ; i ++) { init(n) ; for(int j = i ; j < m ; j ++) { Union(e[j].s , e[j].t) ; if(Find(a) == Find(b)) { MIN = Min(MIN , e[j].speed - e[i].speed) ; break ; } } } if(MIN == inf) printf("-1\n" ) ; else printf("%d\n" , MIN) ; } } return 0;}
hdu1856 题目链接
题意:求最大的连通分量的大小
#include<stdio.h>#define N 10000000int pre[N],num[N];int find(int x){int r=x,k=x,j;while(pre[r]!=r)r=pre[r]; while(k!=r){ j=pre[k]; pre[k]=r; k=j; } return r;}int join(int x,int y){int fx,fy;fx=find(x);fy=find(y);if(fx!=fy){pre[fx]=fy;num[fy]+=num[fx];}return 0;}int main(){int n,x,y,i,j;while(scanf("%d",&n)!=EOF){for(i=1;i<=N;i++){pre[i]=i;num[i]=1;}while(n--){scanf("%d%d",&x,&y); join(x,y);}int max=1;for(j=1;j<=N;j++){if(num[j]>max)max=num[j];}printf("%d\n",max);}return 0;}
hdu1272 题目链接
题意: 任意两个节若满足有且仅有一条道路相通,则输出“Yes”,否则输出“No”
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;const int maxn = 100005 ;int edgenum = 0;int f[maxn] , vis[maxn] ;void Init(){ for(int i = 1 ; i <= 100000 ; i ++) f[i] = i ;}int Find(int x){ while(x != f[x]) { f[x] ==f[f[x]] ; x = f[x] ; } return x ;}void Union(int x , int y){ int fx = Find(x) ; int fy = Find(y) ; if(fx != fy) { f[fy] = fx ; edgenum ++ ; }}int main(){ //freopen("a.txt" , "r" , stdin) ; int ok , x , y , n = 0 , m = 1000000; while(scanf("%d%d" , &x , &y) != EOF ) { memset(vis , 0 , sizeof(vis) ) ; edgenum = 0 ; n = 0 ; if( x == -1 && y == -1) break ; if (x == 0 && y == 0 ) { printf("Yes\n") ; continue ; } Init() ; Union(x , y) ; vis[x] = 1 , vis[y] = 1 ; ok = 1 ; while(scanf("%d%d" , &x ,&y)!= EOF ) { if(x == 0 && y == 0) break ; if(Find(x) == Find(y)) { ok = 0 ;Union(x ,y ) ;} else Union(x ,y ) ; vis[x] = 1 , vis[y] = 1 ; } int vnum = 0 ; for(int i = 1 ; i <= 100000 ; i ++) { if(vis[i]) vnum ++ ; } if(vnum != edgenum + 1) ok = 0 ; if(ok ) printf("Yes\n") ; else printf("No\n") ; } return 0;}hdu 5606链接
题意:n个节点n - 1条边,每条边的权值为0或1,求所有节点i(1 <= i <= n)离节点i最近的节点的数目,并对它们异或操作后输出
思路:求所有连通分量的大小,并对他们进行异或操作
#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn = 100005;int fa[maxn] , ans[maxn] ;void Init(){ for(int i = 1 ; i <= 100000 ; i ++) { fa[i] = i ; ans[i] = 1 ; }}int Find(int x){ if(x == fa[x]) return x ; else return fa[x] = Find(fa[x]) ;}int Union(int x , int y){ int fx = Find(x) ; int fy = Find(y) ; if(fx != fy) { fa[fy] = fx ; ans[fx] += ans[fy] ; //ans[fy] = ans[fx] ; } return 0 ;}int Xor( int a , int b){ return (!a && b) || (a && !b) ;}int main(){ //freopen("a.txt" , "r" , stdin) ; int t , n , u , v , w ; scanf("%d" , &t) ; while(t --) { scanf("%d" , &n) ; Init() ; for(int i = 1 ; i <= n -1 ; i ++) { scanf("%d%d%d" , &u , &v , &w) ; if(w == 0) Union(u , v) ; //权值为0时,为一个连通分量 } for(int i = 1 ; i <= n ; i ++) //更新所有的连通分量大小 { int k = Find(i) ; ans[i] = ans[k] ; } int Ans = ans[1]; for(int i = 2 ; i <= n ; i ++) { Ans = Ans ^ ans[i] ; } printf("%d\n" , Ans) ; } return 0;}
hdu1198 稍微复杂的连通分量表示链接
题意:有11种不同形状的管道,一块田用这11种不同形状的管道覆盖,问这块田中有多少连通分量
思路:本题难点是如何表示连通分量,集合的合并操作怎么表示
#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn = 1000 ;int type[11][4] ={ {1 , 0 , 1 , 0} , {0 , 1 , 1 , 0} , {1 , 0 , 0 , 1} , {0 , 1 , 0 , 1} , {0 , 0 , 1 , 1} , {1 , 1 , 0 , 0} , {1 , 1 , 1 , 0} , {1 , 0 , 1 , 1} , {1 , 1 , 0 , 1} , {0 , 1 , 1 , 1} , {1 , 1 , 1 , 1}} ;char Farm[maxn][maxn] ;int fa[maxn*maxn + 10] ;int cnt , m , n ;void Init(int n){ for(int i = 1 ; i <=n ; i ++) fa[i] = i ; cnt = n ;}int Find(int x){ if(x == fa[x]) return x ; else return fa[x] = Find(fa[x]) ;}void Union(int ax , int ay , int bx , int by , int dir){ if(ax > m || bx > m ) return ; if(ay > n || by > n ) return ; int a = Farm[ax][ay] - 'A' ; int b = Farm[bx][by] - 'A' ; bool flag = false ; if(dir == 0) { if(type[a][1] && type[b][0]) flag = true ; } else { if(type[a][3] && type[b][2]) flag = true ; } if(flag ) { int fx = Find( (ax - 1) * n + ay) ; int fy = Find( (bx - 1) * n + by) ; if(fx != fy) { fa[fx] = fy ; -- cnt ; } }}int main(){ //freopen("a.txt" , "r" , stdin) ; while(scanf("%d%d" , &m , &n) != EOF) { if(n <0 || m < 0) break ; Init(n * m) ; for(int i = 1 ; i <= m ; i ++) scanf("%s" , Farm[i] + 1) ; for(int i = 1 ; i <= m ; i ++) { for(int j = 1 ; j <= n ; j ++) { Union(i , j , i + 1 , j , 1) ; Union(i , j , i , j + 1 , 0) ; } } printf("%d\n" , cnt) ; } return 0 ;}
hdu2473链接
并查集的删除操作
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <set>#pragma comment(linker, “/STACK:1024000000,1024000000”)using namespace std;const int maxn = 1100006 ;int fa[maxn] , id[maxn] ;set<int> S ;int Find(int x){ if(x == fa[x]) return x ; else return fa[x] = Find(fa[x]) ;}void Union(int x ,int y){ int fx = Find(id[x]) ; int fy = Find(id[y]) ; if(fx != fy) fa[fx] = fy ;}int main(){ //freopen("a.txt", "r" , stdin) ; int n , m , kase = 0 , x , y , cnt ; char s[10] ; while(scanf("%d%d" , &n , &m) != EOF) { S.clear() ; if(n == 0 && m == 0) break ; cnt = n ; for(int i = 0 ; i < maxn ; i ++) fa[i] = i ; for(int i = 0 ; i < n ; i ++) id[i] = i ; for(int i = 1 ; i <= m ; i ++) { scanf("%s" , s) ; if(s[0] == 'M') { scanf("%d%d" , &x , &y ) ; Union(x , y) ; } if(s[0] == 'S') { scanf("%d" , &x) ; id[x] = cnt ++ ; //fa[id[x]]=id[x]; } } for(int i = 0 ; i < n ; i ++) { S.insert(Find(id[i])) ; //printf("%d " , Find(id[i])) ; } //printf("\n") ; printf("Case #%d: %d\n" , ++kase , S.size()) ; } return 0;}
0 0
- 并查集部分题目
- 飞鸟集部分
- 并查集题目
- 并查集题目
- 并查集题目推荐
- 并查集题目总结
- poj 并查集题目
- 并查集poj题目
- 【并查集题目总结】
- 并查集的题目
- 并查集经典题目
- 题目 十五 并查集
- POJ并查集题目汇总
- POJ并查集的题目汇总
- hdu 1272 并查集简单题目
- ACM简单题目--并查集
- 题目1012:畅通工程(并查集)
- 并查集的相关题目
- 【小白笔记】IDT源码运行指南(Linux+ffmpeg-0.11.1+opencv-2.4.2)
- Android Wear通过蓝牙调试
- HDU-5781-ATM Mechine(记忆化搜索+期望)
- HDU1010-Tempter of the Bone
- java下载文件中文件名出现中文
- 并查集部分题目
- 关于使用ffmpeg把mp4转化m3u8文件的命令
- 设计模式之代理模式
- Hadoop的Partitioner
- iOS开发之pod 安装 Realm1.0.2 失败的解决办法
- 异常 SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase
- HTML——表单
- CodeForces 482B 有趣的数列 数据结构+线段树+位运算的技巧
- TCP中的一些问题