测试数据:
8
0 2 8 1 0 0 0 0
2 0 6 0 1 0 0 0
8 6 0 7 5 1 2 0
1 0 7 0 0 0 9 0
0 1 5 0 0 3 0 8
0 0 1 0 3 0 4 6
0 0 2 9 0 4 0 3
0 0 0 0 8 6 3 0
8个点,矩阵m[i][j]代表i与j的距离。
kruskal
所有边按长度从小到大排序,如果边的两点连在一起,那么就不添加边,如果不连在一起,就添加边。用并查集维护是否连在一起。
/***********************************************\
|Author: YMC
|Created Time: 2014-5-9 18:25:59
|File Name: kruskal.cpp
|Description:
\***********************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
using namespace std;
#define N 100
#define inf 1<<29
struct seg{
int x,y,c;
}se[1000];
int n;
int ma[N][N];
int fa[N];
int cnt;
void init(int n){
for(int i=1;i<=n;++i) fa[i] = i;
}
int find(int x){
return fa[x] = fa[x] == x ? x : find(fa[x]); //路径优化,可以使查询速度稳定在O(n)
}
void merge(int x,int y){
int a = find(x);
int b = find(y);
fa[a] = b;
}
bool judge(int x,int y){
if(find(x) == find(y)) return true;
else return false;
}
bool cmp(seg a,seg b){
return a.c < b.c;
}
int kruskal()
{
sort(se,se+cnt,cmp); //边排序
init(n); //并查集初始化
int cas = 0;
int ans = 0;
for(int i=0;i<cnt;++i){
int x = se[i].x;
int y = se[i].y;
int c = se[i].c;
if(!judge(x,y)){
//cout<<x<<" "<<y<<endl;
ans += c;
cas ++;
if(cas == n-1) return ans;
}
}
}
int main() {
freopen("input.txt","r",stdin);
scanf("%d",&n);
cnt = 0;
for(int i=1;i<=n;++i){ //输入
for(int j=1;j<=n;++j)
{
scanf("%d",&ma[i][j]);
if(ma[i][j] == 0) ma[i][j] = inf;
}
}
for(int i=1;i<n;++i){ //放入边
for(int j=i+1;j<=n;++j){
seg tp;
tp.x = i;
tp.y = j;
tp.c = ma[i][j];
se[cnt ++] = tp;
}
}
printf("%d\n",kruskal()); //输出最小生成树长度
return 0;
}
prim
类似dijstra,从一个点开始找,每次找到与当前连在一起的点的最短的距离的那个点,然后添加那条当前最短的边。
/***********************************************\
|Author: YMC
|Created Time: 2014-5-9 18:13:44
|File Name: prim.cpp
|Description:
\***********************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
using namespace std;
#define N 100
#define inf 1<<29
int n;
int ma[N][N];
int dis[N];
bool vis[N];
int prim()
{
for(int i=1;i<=n;++i) dis[i] = inf;
memset(vis,false,sizeof(vis));
dis[1] = 0;
vis[1] = true;
for(int i=2;i<=n;++i) dis[i] = ma[1][i];
int ans = 0;
for(int ii = 2;ii<=n;++ii){
int minn = inf;
int pos = -1;
for(int i=2;i<=n;++i){
if(!vis[i] && minn > dis[i]){
minn = dis[i];
pos = i;
}
}
dis[pos] = minn;
vis[pos] = true;
ans += minn;
for(int i=1;i<=n;++i){
if(!vis[i] && dis[i]>ma[pos][i]){
dis[i] = ma[pos][i];
}
}
}
return ans;
}
int main() {
freopen("input.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j)
{
scanf("%d",&ma[i][j]);
if(ma[i][j] == 0) ma[i][j] = inf;
}
}
printf("%d\n",prim());
return 0;
}