并查集---判断图中是否存在环
来源:互联网 发布:网络神曲排行榜前十名 编辑:程序博客网 时间:2024/05/17 04:00
算法描述:
并查集(union-find sets)是一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数、最小公共祖先、带限制的作业排序,还有最完美的应用:实现Kruskar算法求最小生成树。
算法实现:
//并查集判断是否存在环#include <iostream>#include <stdlib.h>#include <string.h>using namespace std;//图中的边struct Edge{ int start;//边的起点 int end;//边的终点};//图结构体struct Graph{ // V顶点个数, E边的个数 int V,E; // 图就是边的集合!!!!! struct Edge* edge;};//创建一个图struct Graph* createGraph(int V, int E){ struct Graph* graph=(struct Graph*) malloc(sizeof(struct Graph)); graph->V = V; graph->E = E; //生成graph->E条边的图 graph->edge = (struct Edge*) malloc(graph->E*sizeof(struct Edge)); return graph;};//查找元素i所在集合(根节点)int find(int parent[], int i){ //一维数组parent[] 来记录子集合 if(parent[i]==-1) {//i的根节点是其自身 return i; } //查找i的根节点所在集合 return find(parent, parent[i]);}//合并集合void join(int parent[], int x, int y){ int xset=find(parent,x); int yset=find(parent,y); if(xset != yset) { parent[xset]=yset; }}//检测是否有环int isCycle(struct Graph* graph){ int *parent = (int*) malloc(graph->V * sizeof(int)); //初始化所有集合(每个节点) //parent[n] 的每个元素都为-1,共有n个子集合,表示集合只有当前顶点一个元素 memset(parent, -1, sizeof(int) * graph->V); //遍历所有边 for(int i=0;i<graph->E;++i) { int x = find(parent, graph->edge[i].start); int y = find(parent, graph->edge[i].end); if(x==y) {//如果在一个集合就找到了环 return 1; } join(parent, x, y); } return 0;}int main(){ /* 创建图 0 | \ | \ 1----2 */ struct Graph* graph = createGraph(3,3); // 添加边 0-1 graph->edge[0].start=0; graph->edge[0].end=1; // 添加边 1-2 graph->edge[1].start=1; graph->edge[1].end=2; // 添加边 0-2 graph->edge[2].start=0; graph->edge[2].end=2; if (isCycle(graph)) { cout<<"graph contains cycle"<<endl; } else { cout<<"graph doesn't contain cycle"<<endl; } return 0;}
九度1024 畅通工程
//使用并查集实现了kruskal算法求最小花费树#include <iostream>#include<stdio.h>#include<stdlib.h>using namespace std;typedef struct node{ int start; int end; int cost;}Node;int father[101];int rank[101];void Make_Set(int M){ for(int i=1;i<=M;i++)//村庄从1开始编号 { father[i]=i; rank[i]=0; }}int Find_Set(int x){ if(x != father[x]) { father[x]=Find_Set(father[x]); } return father[x];}int Union(int x,int y){ x=Find_Set(x); y=Find_Set(y); if(x==y) return 0;//若没有合并,则返回0 if(rank[x]>rank[y]) { father[y]=x; rank[x] += rank[y]; } else { if(rank[x]==rank[y]) { ++rank[y]; } father[x]=y; } return 1;//若进行了合并,则返回1}int cmp(const void *p, const void *q){ Node * p1=(Node *)p; Node * q1=(Node *)q; return p1->cost - q1->cost;//从小到大}int main(){ int N,M; int ans; int cnt; Node road[5000]; while(cin>>N>>M&&N) { for(int i=0;i<N;i++) { scanf("%d%d%d",&road[i].start,&road[i].end,&road[i].cost); } qsort(road,N,sizeof(Node),cmp);//将N条道路的花费值从小到大排序 Make_Set(M); ans=0; cnt=0; for(int i=0;i<N;i++) { if(cnt==M-1)//按照树的定义,M个点有M-1条连线 break; if(Union(road[i].start,road[i].end)) { ++cnt; ans += road[i].cost; } } if(cnt==M-1)//实现了kruskal算法求最小花费树 { printf("%d\n",ans); } else { printf("?\n"); } } return 0;}
0 0
- 并查集---判断图中是否存在环
- 并查集-判断无向图是否存在环
- NWU CCCC 1017(HDU 1272改编 并查集判断图是否存在环)
- UVA 1160 - X-Plosives 即LA3644 并查集判断是否存在环
- hdu1272小希的迷宫(并查集--判断是否有环的存在)
- 杭电1272~~小希的迷宫——并查集判断是否存在环
- UVA 1160 - X-Plosives 并查集判断是否存在环
- 判断图中是否存在环
- 并查集-用并查集判断图中是否有环(能够应用到kruskal的最小生成树)
- hdu1272小希的迷宫 并查集判断图中是否有回路
- LA3644 利用并查集判断是否有环
- HUD 1272 (并查集判断是否有环)
- HDU 1325(并查集判断一个图是否是一棵树)
- 使用并查集判断无向图是否连通
- 【并查集】判断是否为树
- 【并查集】判断是否为树
- 判断表中某一字段是否存在并删除
- 判断表中字段是否存在并添加
- linux系统下的档案权限和目录配置
- spark学习1
- centos安装wine
- 微软100题(59)不能被继承的类
- 数据结构与算法7: 二叉搜索树基本操作(Binary search tree basic operation )
- 并查集---判断图中是否存在环
- 预编译头文件
- markdown编辑器 基本语法
- 冒泡排序
- 关于DC
- Maven nexus安装、配置和使用
- java线程同步:使用Object的wait,notify,notifyAll做线程调度
- #219 Contains Duplicate II
- Python中的变量