最小生成树算法(Prim+Kruskal)
2016-08-15 16:34
447 查看
Prim算法:
首先任取一个点u加入最小生成树
1)更新从其他点v出发到u的距离储存在dist中
2)然后选一个dist值最小的点u(1)再收入到最小生成树中,再重复1)
当点全部收录最小生成树时,算法结束
代码如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=1<<30;
struct Edge{
int vex;
int w;
Edge(int v=0,int w=INF):vex(v),w(w){}
bool operator < (const Edge& e) const {
return w>e.w;
}
};
//图是邻接表存储 G[u]储存u点出发所有的点
vector<vector<Edge> > G(110); //比Vector<Edge> G[110] 快
int HeapPrim(int n) //返回mst的最小权值
{
priority_queue<Edge> PQ;
vector<int> dist(n,INF); //所有点到mst的最短距离
vector<bool> used(n,false);
int totw=0; //mst 的总权值
int DoneNum=0; //收入的点数
PQ.push(Edge(0,0));
while(DoneNum<n&&!PQ.empty())
{
Edge e=PQ.top(); PQ.pop();
while(used[e.vex]&&!PQ.empty())
e=PQ.top(),PQ.pop();
if(used[e.vex]) continue; //不能 if(PQ.empty())因为第一个点就是empty的
totw+=e.w;
used[e.vex]=true;
DoneNum++;
for(int i=0;i<G[e.vex].size();i++) //该点连接的所有边
{
int v=G[e.vex][i].vex;
int w=G[e.vex][i].w;
if(!used[v]&&dist[v]>w){ //更新到mst的dist值
dist[v]=w;
PQ.push(Edge(v,w));
}
}
}
if(DoneNum<n) return -1;
return totw;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++) G[i].clear();
for(int i=0;i<n;i++) //邻接矩阵读取
for(int j=0;j<n;j++)
{
int w;
cin>>w;
if(i!=j) G[i].push_back(Edge(j,w));
}
cout<<HeapPrim(n)<<endl;
}
return 0;
}
kruskal算法:
更简单,每条边权值排排序,再从小到大选n-1个边就好了 (n为顶点数)
但要注意每条边的两个顶点不能都在同一个集合,所以要用到并查集优化了
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10000+5;
int n,m; //n个点 , m条边
struct Edge{
int from,to,weight;
Edge(int f,int t,int w):from(f),to(t),weight(w){}
bool operator < (const Edge& e) const {
return weight<e.weight;
}
};
vector<Edge> edges;
int p[maxn];
int find(int x) {
return p[x]==x?x:p[x]=find(p[x]);
}
int Kruskal()
{
int TotW=0;
for(int i=0;i<n;i++) p[i]=i;
sort(edges.begin(),edges.end());
int done=0;
for(int i=0;i<m;i++)
{
Edge e=edges[i];
int u=e.from, v=e.to, w=e.weight;
int up=find(u), vp=find(v);
if(up!=vp) TotW+=w,p[up]=vp,done++;
if(done==n-1) break; //到n-1条边就结束
}
return TotW;
}
int main()
{
while(cin>>n)
{
edges.clear();
for(int i=0;i<n;i++) //邻接矩阵读取
for(int j=0;j<n;j++)
{
int w;
cin>>w;
if(i!=j) edges.push_back(Edge(i,j,w));
}
m=edges.size();
cout<<Kruskal()<<endl;
}
return 0;
}
首先任取一个点u加入最小生成树
1)更新从其他点v出发到u的距离储存在dist中
2)然后选一个dist值最小的点u(1)再收入到最小生成树中,再重复1)
当点全部收录最小生成树时,算法结束
代码如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=1<<30;
struct Edge{
int vex;
int w;
Edge(int v=0,int w=INF):vex(v),w(w){}
bool operator < (const Edge& e) const {
return w>e.w;
}
};
//图是邻接表存储 G[u]储存u点出发所有的点
vector<vector<Edge> > G(110); //比Vector<Edge> G[110] 快
int HeapPrim(int n) //返回mst的最小权值
{
priority_queue<Edge> PQ;
vector<int> dist(n,INF); //所有点到mst的最短距离
vector<bool> used(n,false);
int totw=0; //mst 的总权值
int DoneNum=0; //收入的点数
PQ.push(Edge(0,0));
while(DoneNum<n&&!PQ.empty())
{
Edge e=PQ.top(); PQ.pop();
while(used[e.vex]&&!PQ.empty())
e=PQ.top(),PQ.pop();
if(used[e.vex]) continue; //不能 if(PQ.empty())因为第一个点就是empty的
totw+=e.w;
used[e.vex]=true;
DoneNum++;
for(int i=0;i<G[e.vex].size();i++) //该点连接的所有边
{
int v=G[e.vex][i].vex;
int w=G[e.vex][i].w;
if(!used[v]&&dist[v]>w){ //更新到mst的dist值
dist[v]=w;
PQ.push(Edge(v,w));
}
}
}
if(DoneNum<n) return -1;
return totw;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++) G[i].clear();
for(int i=0;i<n;i++) //邻接矩阵读取
for(int j=0;j<n;j++)
{
int w;
cin>>w;
if(i!=j) G[i].push_back(Edge(j,w));
}
cout<<HeapPrim(n)<<endl;
}
return 0;
}
kruskal算法:
更简单,每条边权值排排序,再从小到大选n-1个边就好了 (n为顶点数)
但要注意每条边的两个顶点不能都在同一个集合,所以要用到并查集优化了
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=10000+5;
int n,m; //n个点 , m条边
struct Edge{
int from,to,weight;
Edge(int f,int t,int w):from(f),to(t),weight(w){}
bool operator < (const Edge& e) const {
return weight<e.weight;
}
};
vector<Edge> edges;
int p[maxn];
int find(int x) {
return p[x]==x?x:p[x]=find(p[x]);
}
int Kruskal()
{
int TotW=0;
for(int i=0;i<n;i++) p[i]=i;
sort(edges.begin(),edges.end());
int done=0;
for(int i=0;i<m;i++)
{
Edge e=edges[i];
int u=e.from, v=e.to, w=e.weight;
int up=find(u), vp=find(v);
if(up!=vp) TotW+=w,p[up]=vp,done++;
if(done==n-1) break; //到n-1条边就结束
}
return TotW;
}
int main()
{
while(cin>>n)
{
edges.clear();
for(int i=0;i<n;i++) //邻接矩阵读取
for(int j=0;j<n;j++)
{
int w;
cin>>w;
if(i!=j) edges.push_back(Edge(i,j,w));
}
m=edges.size();
cout<<Kruskal()<<endl;
}
return 0;
}
相关文章推荐
- 算法记录---最小生成树【kruskal&&prim】
- 最小生成树算法(Prim和Kruskal)
- 最小生成树 ,prim 和Kruskal 算法
- 关于图的常用算法——Dijkstra单源最短路径、Floyd多源最短路径、Prim和Kruskal最小生成树算法
- 图论中最小生成树算法-Prim(普里姆)算法、kruskal(克鲁斯卡尔避圈法)算法、破圈算法
- 最小生成树 Prim(普里姆)算法和Kruskal(克鲁斯特尔)算法
- 数据结构 学习笔记(九):图(下):最小生成树(Prim,Kruskal 算法),拓扑排序 AOV,关键路径 AOE
- 最小生成树的两种算法图解(Kruskal与prim)
- 算法复习 - 最小生成树算法 Prim、Kruskal(普里姆算法、 克鲁斯卡尔算法)
- hdu 1863 畅通工程 最小生成树模板入门题 prim+kruskal两种算法AC。
- 最小生成树算法(prim&kruskal)
- 最小生成树算法Prim、Kruskal
- kruskal与prim最小生成树算法
- 最小生成树两种算法。kruskal和prim
- 图的广度遍历、深度遍历及最小生成树书算法(Prim、Kruskal)
- 最小生成树算法(Prim和Kruskal)
- hdu 1162 Eddy's picture 最小生成树入门题 Prim+Kruskal两种算法AC
- 算法整理:最小生成树(mst)-Prim+Kruskal
- poj 1258 小白算法练习 Agri-Net 最小生成树 prim kruskal
- 数据结构之最小生成树的Prim和Kruskal`s 算法