Kruskal算法
关于图的几个概念定义:
- 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。
- 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。
- 连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。
- 生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。
-
最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
- Kruskal算法即为加边法
-
- #include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
int f[120];
typedef struct dao
{
int a;
int b;
double dis;
}dao;
bool cmd(dao a,dao b)//排序
{
return a.dis <b.dis;
}
int find(int n)//找根节点
{
if(f[n]==n)return n;
else return f[n]=find(f[n]);
}
void init()//初始化
{
for(int i=0;i<120;i++)
f[i]=i;
}
bool heb(int a,int b)//合并并判断是否为环
{
int fa=find(a),fb=find(b);
if(fa!=fb)
{
f[fa]=fb;
return true;
}
return false;
}
int main()
{
int t,c;
while(cin>>t)
{
while(t--)
{
dao s[10005];
cin>>c;
double x[101],y[101];
for(int i=0;i<c;i++)
{
cin>>x[i]>>y[i];
}
int k=1;
for(int i=0;i<c-1;i++)
{
for(int j=i+1;j<c;j++)
{
double num=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
if(num>=100&&num<=1000000)
{
s[k].a =i;
s[k].b =j;
s[k].dis =sqrt(num);
k++;
}
}
}
sort(s,s+k,cmd);
init();
double sum=0;
int flag=0;
for(int i=0;i<k;i++)
{
if(heb(s[i].a ,s[i].b ))
{
sum+=s[i].dis ;
flag++;
}
}
if(flag==c-1)printf("%.1lf\n",sum*100);
else cout<<"oh!"<<endl;
}
}
return 0;
}