克鲁斯卡尔算法(kruskal)(并查集的简单应用)
2015-10-23 21:11
295 查看
克鲁斯卡尔(Kruskal)算法(只与边相关)
算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。
算法过程:
1.将图各边按照权值进行排序
2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。
3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。
克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树。
水题,zoj1203:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1203
题意:给定N各城市位置,计算连接这N个城市的最短路线长度。
计算并储存每对城市的路线长度,用kruskal算法求解,注意输出格式!
水题:zoj1718:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=718
计算两个空间站中心距离d,判断是否交叉或重合(即两空间站半径与d的大小关系),接下来就相当于模板题了。
算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。
算法过程:
1.将图各边按照权值进行排序
2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。
3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。
克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=1005; struct node { int u,v,w; bool operator< (const node& b) const { return w<b.w; } }; int n,m; node edge[maxn]; int parent[maxn]; int k; void init() { k=0; memset(parent,-1,sizeof(parent)); } int Find(int num) { int s; for(s=num;parent[s]>=0;s=parent[s]); while(s!=num) { int tmp=parent[num]; parent[num]=s; num=tmp; } return s; } int Union(int R1,int R2) { int r1=Find(R1); int r2=Find(R2); if(r1==r2) return 0; int tmp=parent[r1]+parent[r2]; //假如r2所含结点数更多 if(parent[r1]>parent[r2]) { parent[r1]=r2; parent[r2]=tmp; } else { parent[r2]=r1; parent[r1]=tmp; } return 1; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=m;i++) { scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } sort(edge+1,edge+m+1); init(); int num=0; for(int i=1;i<=m;i++) { if(Union(edge[i].u,edge[i].v)) { k+=edge[i].w; cout<<edge[i].u<<" "<<edge[i].v<<" "<<edge[i].w<<endl; num++; } if(num>=n-1) break; } cout<<k<<endl; } return 0; }
水题,zoj1203:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1203
题意:给定N各城市位置,计算连接这N个城市的最短路线长度。
计算并储存每对城市的路线长度,用kruskal算法求解,注意输出格式!
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N=105; struct node { int u,v; double w; bool operator<(const node& b)const { return w<b.w; } }edge[N*N]; double lg; double x ,y ; int parent ;//为负数时表示该节点连有parent【N】-1个结点 int n; int tmp; void init() { lg=0; memset(parent,-1,sizeof(parent)); } int Find(int t) { int s=t; while(parent[s]>=0) { s=parent[s]; } while(t!=s) { int tt=parent[t]; parent[t]=s; t=tt; } return s; } void Union(node p) { int r1=Find(p.u); int r2=Find(p.v); int t=parent[r1]+parent[r2]; if(parent[r1]>parent[r2]) { parent[r1]=r2; parent[r2]=t; } else { parent[r2]=r1; parent[r1]=t; } } void kruskal() { int num=0; for(int i=0;i<tmp;i++) { int u=edge[i].u; int v=edge[i].v; if(Find(u)!=Find(v)) { lg+=edge[i].w; num++; Union(edge[i]); } if(num>=n-1) return; } } int main() { //freopen("in.txt","r",stdin); int ttt=0; while(cin>>n) { if(n==0) break; init(); for(int i=0;i<n;i++) { scanf("%lf%lf",&x[i],&y[i]); } tmp=0; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { edge[tmp].u=i; edge[tmp].v=j; edge[tmp++].w=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } } sort(edge,edge+tmp); kruskal(); if(ttt>=1) cout<<endl; printf("Case #%d:\n",++ttt); printf("The minimal distance is: %.2lf\n",lg); } return 0; };
水题:zoj1718:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=718
计算两个空间站中心距离d,判断是否交叉或重合(即两空间站半径与d的大小关系),接下来就相当于模板题了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N=105; struct node { int u,v; double w; bool operator <(const node& b) const { return w<b.w; } }edge[N*N]; int n; int lg; double weight; double x ,y ,z ,r ; int parent ; void init() { lg=0; weight=0; memset(parent,-1,sizeof(parent)); } int Find(int tmp) { int s=tmp; while(parent[s]>=0) { s=parent[s]; } while(s!=tmp) { int t=parent[tmp]; parent[tmp]=s; tmp=t; } return s; } void Union(int u,int v) { int r1=Find(u); int r2=Find(v); int tmp=parent[r1]+parent[r2]; if(r1>r2) { parent[r1]=r2; parent[r2]=tmp; } else { parent[r2]=r1; parent[r1]=tmp; } } void kruskal() { int sum=0; for(int i=0;i<lg;i++) { int u=edge[i].u; int v=edge[i].v; if(Find(u)!=Find(v)) { sum++; weight+=edge[i].w; Union(u,v); } if(sum>=n-1) return; } } int main() { //freopen("in.txt","r",stdin); while(cin>>n) { if(n==0) break; init(); for(int i=0;i<n;i++) scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]); for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { double d=sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2)+pow(z[i]-z[j],2))-r[i]-r[j]; if(d<=0) d=0; edge[lg].u=i; edge[lg].v=j; edge[lg++].w=d; } } sort(edge,edge+lg); kruskal(); printf("%.3f\n",weight); } return 0; }
相关文章推荐
- 【JAVA知识】HashTable和HashMap的区别,并简述Hashmap的实现原理
- oVirt介绍及安装记录
- Delphi 实现任务栏多窗口图标显示(使用WS_EX_APPWINDOW风格)
- 初学Java的HelloWorld以及常见问题
- 功能测试
- 各种排序算法稳定性的总结!!!
- CGridCtrl 添加button (CGridCellButton类)
- iOS消息传递机制
- c++学习笔记(九):运算符重载进阶
- 迅雷是怎么下载的
- 黑马程序员——Java 基础:静态
- Andriod异步消息处理机制解析
- PPT基础与进阶
- 51nod 1099:任务执行顺序 贪心
- ftp 上传 文件 下载文件
- 51nod 1099:任务执行顺序 贪心
- find the most comfortable road(并差集,找差值最小的权值)
- Command(命令模式)
- POJ 2253 Frogger 最短路径 Floyed-Warshall算法
- 蓝懿ios 技术内容和心得 10。23