一.prime算法:
具体的数据结构原理不再赘述,这里只贴上两种算法生成过程~
生成过程:
1 -> 3 : 1
3 -> 6 : 4
6 -> 4: 2
3 -> 2 : 5
2 -> 5 : 3
题目描述:
不解释了,直接上代码
prim求最小生成树利用到了dijkstra()算法,只需要改变一下dis数组的含义就可以。
dijkstra中dis数组表示的是当前点到源点的最小距离,而在这里表示的是当前点到已经生成的树的最小距离。
只需要将代码中的dis[i]=min(dis[i],dis[pos]+map[pos][i]);
改为:dis[i]=min(dis[i],map[pos][i])
#include<iostream>
#include<cstring>
using namespace std;
int map[205][205];
int book[205];
int ans;
const int inf=0x3f3f3f3f;
int dis[102];//这里表示的不是到源点的最短距离,而是到已经选中的树的所有的点的最短距离
int m,n;
void prim()
{
memset(book,0,sizeof(book));
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
for(int k=1;k<=n;k++)
{
int pos,minn=inf;
for(int i=1;i<=n;i++)
{
if(!book[i]&&dis[i]<minn)
{
minn=dis[i];
pos=i;
}
}
ans+=minn;
book[pos]=1;
for(int i=1;i<=n;i++)
{
//这个是dijkstra算法的写法
//dis[i]=min(dis[i],dis[pos]+map[i][pos]);
dis[i]=min(dis[i],map[i][pos]);
}
}
}
int main()
{
while(cin>>n>>m)
{
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=(i==j?0:inf);
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
map[x][y]=map[y][x]=z;
}
prim();
cout<<ans<<endl;
}
return 0;
}
二“Kruskal算法
1 -> 3 : 1
4 -> 6 : 2
2 -> 5 : 3
3 -> 4 : 4
2 -> 3 : 5
利用到并查集的算法,直接上代码:
时间复杂度:O(mlogm+mlogn)=O(mlogm).对所有的边进行排序,从m条边中选出n-1条边;
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,m;
struct edge{
int u,v;
int w;
friend bool operator <(edge e1,edge e2)
{
return e1.w<e2.w;
}
};
vector<edge>e;
int f[101];
int ans;
void init()
{
for(int i=1;i<=n;i++)
f[i]=i;
}
int find(int x)
{
if(f[x]==x)return x;
else
return f[x]=find(f[x]); //注意这里传入的参数是f[x];
}
int _merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
f[fx]=fy;
return 1;
}
return 0;
}
int main()
{
while(cin>>n>>m,n+m)
{
ans=0;
e.clear();
int cnt=0;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
e.push_back(edge{x,y,z});
}
sort(e.begin(),e.end());
init();
for(int i=0;i<m;i++)
{
if(_merge(e[i].u,e[i].v))
{
ans+=e[i].w;
cnt++;
if(cnt==n-1)break;
}
}
cout<<ans<<endl;
}
return 0;
}
/*
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
*/