prim算法
/*************************************************************************
* author:crazy_石头
* algorithm:prim
* date:2013/09/29
* 程序功能:MST
* 算法流程:1.先选取一个点作起始点,然后选择它邻近的权值最小的点
(如果有多个与其相连的相同最小权值的点,随便选取一个)。如1作为起点。
2.再在伸延的点找与它邻近的两者权值最小的点。
**************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <time.h>
#include <queue>
#include <algorithm>
using namespace std;
#define A system("pause")
#define N 100005
#define M 400010
#define INF INT_MAX
const int maxn=1000;
int dis[maxn],vis[maxn],pre[maxn];
int map[maxn][maxn];
//记录路径或者说是加入的边;
int n,e;//顶点数和边数;
int a,b;
inline int prim()
{
int i,j,pos,res=0;
int cnt=1;
for(i=1;i<=n;i++)
dis[i]=map[1][i],pre[i]=1;
memset(vis,0,sizeof(vis));
vis[1]=1;
dis[1]=0;
for(j=1;j<=n;j++)
{
int minm=INF;
for(i=1;i<=n;i++)
{
if(!vis[i]&&minm>dis[i])
{
minm=dis[i];
pos=i;//第一次找出最短距离及对应的点;
a=i,b=pre[i];
}
}
vis[pos]=1;
if(minm==INF)
break;
res+=minm;
printf("(%d,%d)\n",b,a);
for(i=1;i<=n;i++)
{
if(!vis[i]&&map[pos][i]!=INF&&map[pos][i]<dis[i])
{
dis[i]=map[pos][i];
pre[i]=pos;
}
}
}
return res;
}
int main()
{
cin>>n>>e;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
i==j?map[i][j]=0:map[i][j]=INF;
}
}
while(e--)
{
int a,b,cost;
cin>>a>>b>>cost;
map[a][b]=map[b][a]=cost;
}
int ans=prim();
for(int i=1;i<=n;i++)
printf("dis[%d]==%d \n",i,dis[i]);
printf("weight: %d\n",ans);
return 0;
}
/*test:
6 10
1 2 6
1 4 5
1 3 1
2 3 5
2 5 3
3 5 6
3 6 4
4 6 2
5 6 6
3 4 5
output:15
*/
kruscal算法
/*************************************************************************
* author:crazy_石头
* algorithm:Kruscal
* date:2013/09/29
* 程序功能:MST
* 算法流程:初始时全为孤立的点,图的边就绪状态为非降序排列。然后一次遍历图中的所有边(u, v),
使用并查集的思想,find_set(u)如果不等于find_set(v),也就是u和v不在同一个集合中,
那么相当于判断了添加了边(u, v)不会成环,同时合并u和v(使用union_set(u, v)).
当所有的顶点都添加到集合中去了,算法完毕。
**************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <time.h>
#include <queue>
#include <algorithm>
using namespace std;
#define C system("pause")
#define INF INT_MAX
const int maxn=1000;
int p[maxn];
int n,e;
struct Edge
{
int a;
int b;
int weight;
bool operator<(const Edge &A)const
{
return weight<A.weight;
}
}edge[maxn*maxn];
inline int Find_set(int x)
{
return p[x]==-1?x:p[x]=Find_set(p[x]);//未带路径压缩;
}
int main()
{
int ans=0,cnt=0;
cin>>n>>e;
for(int i=0;i<e;i++)
{
cin>>edge[i].a>>edge[i].b>>edge[i].weight;
}
sort(edge,edge+e);
memset(p,-1,sizeof(p));
for(int i=0;i<e;i++)
{
if(cnt==n-1)
break;
int a=Find_set(edge[i].a);
int b=Find_set(edge[i].b);
printf("edge[%d].a==%d\tedge[%d].b==%d\ta==%d b==%d,<%d,%d>edge[%d].cost==%d\n",i,edge[i].a,i,edge[i].b,a,b,a,b,i,edge[i].weight);
if(a!=b)
{
cnt++;
p[a]=b;
ans+=edge[i].weight;//有一条边并查集找到根后,a==b,continue掉了,所以共5条边六个顶点时完成算法;
printf("应该加入的边为<%d,%d>\n",edge[i].a,edge[i].b);
printf("当前的ans==%d\n",ans);
}
else
continue;
}
printf("%d\n",ans);
return 0;
}
/*test:
6 10
1 2 6
1 4 5
1 3 1
2 3 5
2 5 3
3 5 6
3 6 4
4 6 2
5 6 6
3 4 5
output:15
*/