hdu 1102
题意:n个点 给出各点之间的距离,并且有的点之间已经有联系,求让所有的点联系最短的路径(最小生成树);
Kruskal算法特点是不断的选取最短的边 并且各边不能形成环 直到 生成树(并茶几为1);
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Edge
{
int u,v,w;
}edge[11111];
int map[111][111];
int n;
int fa[111];
bool cmp(Edge a,Edge b)
{
if(a.w<b.w)
return true;
return false;
}
int find(int x)
{
int y=x;
while(fa[y]!=y)
{
y=fa[y];
}
return y;
}
void un(int x,int y)
{
x=find(x),y=find(y);
fa[x]=y;
return ;
}
bool f()
{
int sum=0,i;
for(i=1;i<=n;i++)
if(fa[i]==i)
sum++;
if(sum==1)
return true;
return false;
}
void Kruskal(int e)
{
int sumweight=0;
int i;
int u,v;
for(i=0;i<e;i++)
{
if(f())//判断此树是否生成
break;
u=find(edge[i].u),v=find(edge[i].v);
if(map[edge[i].u][edge[i].v])
continue;
map[edge[i].u][edge[i].v]=1;
map[edge[i].v][edge[i].u]=1;
if(u==v)
continue;
un(edge[i].u,edge[i].v);//合并两点
sumweight+=edge[i].w;//累加权值
}
cout<<sumweight<<endl;
return ;
}
int main()
{
int w,k,i,j;
int x,c;
while(cin>>n)
{
k=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cin>>map[i][j];
}
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
{
if(i==j)
continue;
if(map[i][j]==map[j][i])
{
edge[k].u=i;edge[k].v=j;edge[k++].w=map[i][j];
continue;
}
else
{
edge[k].u=i;edge[k].v=j;edge[k++].w=map[i][j];
edge[k].u=j;edge[k].v=i;edge[k++].w=map[j][i];
}
}
for(i=1;i<=n;i++)
fa[i]=i;
memset(map,0,sizeof(map));
cin>>x;
c=x;
while(x--)
{
cin>>i>>j;
un(i,j);
map[i][j]=map[j][i]=1;
}
sort(edge,edge+k,cmp);
Kruskal(k);
}
return 0;
}