最小生成树 ,prim 和Kruskal 算法
2017-05-21 09:45
405 查看
prim 算法 类似于dijstra算法, 个人认为是 dijstra的简化版; 两个算法都是记录从v0- vn 点之间 距离的最短
找到后 相加就可以
Kruskal 算法 用到 优先队列来 选择权值 由小到大,
并查集 来 看是不是形成回路(说白了就是 两个点的上级是不是一个人,不是 加进去,是放弃)
Kruskal算法的过程:
(1) 将全部边按照权值由小到大排序。
(2) 按顺序(边权由小到大的顺序)考虑每条边,只要这条边和我们已经选择的边不构成圈,就保留这条边,否则放弃这条边。
算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。
两个 都没有记录路径(没写- -)
prim 算法: 模板
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stdio.h>
const int inf=1<<29;
using namespace std;
int maps[1010][1010];
int dis[101000];
int n,m,sum;
int vis[10100];
void prim(int v0)
{
int i,j,mid,k;
for(i=1;i<=n;i++)
{
dis[i]=maps[v0][i];
}
memset(vis,0,sizeof(vis));
vis[v0]=true;
for(i=1;i<n;i++)
{
mid=inf;
k=-1;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<mid)
{
mid=dis[j];
k=j;
}
}
sum+=dis[k];
vis[k]=true;
for(j=1;j<=n;j++)
{
if(!vis[j]&&maps[k][j]<dis[j])
dis[j]=maps[k][j];
}
}
}
int main()
{
cin>>n>>m;
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
maps[i][i]=0;
else
maps[i][j]=inf;
}
int x,y,z;
for(i=0;i<m;i++)
{
cin>>x>>y>>z;
// if(z<maps[x][y])
maps[x][y]=maps[y][x]=z;
}
sum=0;
prim(1);
cout<<sum<<endl;
return 0;
}
kruskal 算法模板:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stdio.h>
const int inf=1<<29;
using namespace std;
typedef long long ll;
struct edge{
int f;
int t;
int cost;
friend bool operator < (const edge &x,const edge &y)
{
return x.cost>y.cost;// 优先队列 由小到大排列; >
}
};
int sum;
int boss[10100];
int n,m;
priority_queue <edge> Q;// 优先队列
void table()
{
while(!Q.empty())Q.pop();
for(int i=0;i<1010;i++)
boss[i]=i;
}
int finds(int x)
{
int k=x;
while(boss[k]!=k)
k=boss[k];
return k;
}
void Kruskal()
{
int num=0;
while(!Q.empty()&&num!=n-1)
{
edge u=Q.top();
Q.pop();
int fx=finds(u.f);
int fy=finds(u.t);
if(fx!=fy)// 构不成回路 上级不同
{
boss[fx]=fy;//
4000
合并上级
sum+=u.cost;
num++;
}
}
}
int main()
{
cin>>n>>m;
table();
int i,j,f,t,cost;
for(i=0;i<m;i++)
{
cin>>f>>t>>cost;
edge node;
node.f=f;
node.t=t;
node.cost=cost;
Q.push(node);
}
sum=0;
Kruskal();
cout<<sum<<endl;
return 0;
}
找到后 相加就可以
Kruskal 算法 用到 优先队列来 选择权值 由小到大,
并查集 来 看是不是形成回路(说白了就是 两个点的上级是不是一个人,不是 加进去,是放弃)
Kruskal算法的过程:
(1) 将全部边按照权值由小到大排序。
(2) 按顺序(边权由小到大的顺序)考虑每条边,只要这条边和我们已经选择的边不构成圈,就保留这条边,否则放弃这条边。
算法 成功选择(n-1)条边后,形成一个棵最小生成树,当然如果算法无法选择出(n-1)条边,则说明原图不连通。
两个 都没有记录路径(没写- -)
prim 算法: 模板
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stdio.h>
const int inf=1<<29;
using namespace std;
int maps[1010][1010];
int dis[101000];
int n,m,sum;
int vis[10100];
void prim(int v0)
{
int i,j,mid,k;
for(i=1;i<=n;i++)
{
dis[i]=maps[v0][i];
}
memset(vis,0,sizeof(vis));
vis[v0]=true;
for(i=1;i<n;i++)
{
mid=inf;
k=-1;
for(j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<mid)
{
mid=dis[j];
k=j;
}
}
sum+=dis[k];
vis[k]=true;
for(j=1;j<=n;j++)
{
if(!vis[j]&&maps[k][j]<dis[j])
dis[j]=maps[k][j];
}
}
}
int main()
{
cin>>n>>m;
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
maps[i][i]=0;
else
maps[i][j]=inf;
}
int x,y,z;
for(i=0;i<m;i++)
{
cin>>x>>y>>z;
// if(z<maps[x][y])
maps[x][y]=maps[y][x]=z;
}
sum=0;
prim(1);
cout<<sum<<endl;
return 0;
}
kruskal 算法模板:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stdio.h>
const int inf=1<<29;
using namespace std;
typedef long long ll;
struct edge{
int f;
int t;
int cost;
friend bool operator < (const edge &x,const edge &y)
{
return x.cost>y.cost;// 优先队列 由小到大排列; >
}
};
int sum;
int boss[10100];
int n,m;
priority_queue <edge> Q;// 优先队列
void table()
{
while(!Q.empty())Q.pop();
for(int i=0;i<1010;i++)
boss[i]=i;
}
int finds(int x)
{
int k=x;
while(boss[k]!=k)
k=boss[k];
return k;
}
void Kruskal()
{
int num=0;
while(!Q.empty()&&num!=n-1)
{
edge u=Q.top();
Q.pop();
int fx=finds(u.f);
int fy=finds(u.t);
if(fx!=fy)// 构不成回路 上级不同
{
boss[fx]=fy;//
4000
合并上级
sum+=u.cost;
num++;
}
}
}
int main()
{
cin>>n>>m;
table();
int i,j,f,t,cost;
for(i=0;i<m;i++)
{
cin>>f>>t>>cost;
edge node;
node.f=f;
node.t=t;
node.cost=cost;
Q.push(node);
}
sum=0;
Kruskal();
cout<<sum<<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)