http://poj.org/problem?id=2421
题目大意
给你一些点,求最小生成树,但有些点已经连好了。
算法思想:最小生成树,kruskal可过,区别仅仅在于存图时多一步。
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int num=0,fa[1001],f[101][101];
struct dist
{
int x,y,l,ne;
bool operator <(const dist b)const
{
return l<b.l;
}
}e[10000];
void put(int x,int y,int l)
{
num++;
e[num].x=x;
e[num].y=y;
e[num].l=l;
}
int get(int x)
{
if (fa[x]==x) return x;
else return(get(fa[x]));
}
int main()
{
int n,x,y,l;
scanf("%d",&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
scanf("%d",&l);
f[i][j]=l;
}
int q;
scanf("%d",&q);
for (int i=1;i<=q;i++) //读入已连号的边,先标记为-1;
{
scanf("%d%d",&x,&y);
f[x][y]=-1;
}
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++) //建图(按条件连边);
{
if (f[i][j]==-1) //已连好,相当于该边的代价为0;
put(i,j,0);
else put(i,j,f[i][j]);
}
sort(e+1,e+num+1); //keuskal;
for (int i=1;i<=n;i++)
{
fa[i]=i;
}
int total=0,f1,f2,ans=0;
for (int i=1;i<=num;i++)
{
f1=get(e[i].x);
f2=get(e[i].y);
if (f1!=f2)
{
total++;
ans+=e[i].l;
fa[f1]=f2;
};
if (total==n-1)
{
break;
}
}
printf("%d",ans);
return 0;
}