最小生成树
一.prime 算法
直接暴力每个点,以每个点为起点找出最优解(距离最短)
#include <bits/stdc++.h>
using namespace std;
typedef __int64 ll;
const int N=107,INF=0x3f3f3f3f;
int cost[N][N],lc[N],vis[N];
int n;
int prime()
{
for(int i=1; i<=n; i++)
{
int mi=INF,pos;
for(int j=1; j<=n; j++)
if(!vis[j]&&mi>lc[j])
mi=lc[j],pos=j;
vis[pos]=1;//找出花费最少的点后,标记掉避免二次计算
for(int j=1; j<=n; j++)
if(!vis[j]&&lc[j]>cost[j][pos])
lc[j]=cost[j][pos];
}
int ans=0;
for(int i=1; i<=n; i++)
ans+=lc[i];//答案为每个点的花费总和
return ans;
}
int main()
{
int q;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&cost[i][j]); //i->j的花费
scanf("%d",&q);
for(int i=0; i<q; i++)
{
int a,b;
scanf("%d%d",&a,&b);
cost[a][b]=0;
cost[b][a]=0;
}
memset(lc,INF,sizeof(lc));//每个点的最低花费
memset(vis,0,sizeof(vis));//是否访问过这个点
lc[1]=0;//起点花费为0
printf("%d\n",prime());
}
}
二 . kruskal
已经连接的点并入一个集合(并查集)
#include <bits/stdc++.h>
using namespace std;
typedef __int64 ll;
const int N=107,INF=0x3f3f3f3f;
int f[N],k;
struct node
{
int s,d,co;
} po[N*N];
int _find(int x)
{
if(f[x]!=x) return f[x]=_find(f[x]);
return f[x];
}
int cmp(node a,node b)
{
return a.co<b.co;
}
int kruskal()
{
int ans=0;
for(int i=0; i<k; i++)
{
int fa=_find(po[i].s);
int fb=_find(po[i].d);
if(fa!=fb)//不在一个集合内就放入并建边,费用放进ans
{
ans+=po[i].co;
f[fa]=fb;
}
}
return ans;
}
int main()
{
int n,q;
while(~scanf("%d",&n))
{
k=0;
for(int i=0; i<=n; i++)
f[i]=i;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
scanf("%d",&po[k].co);
po[k].s=i,po[k].d=j;
k++;
}
int q;
scanf("%d",&q);
for(int i=0; i<q; i++)
{
int a,b;
scanf("%d%d",&a,&b);
int fa=_find(a);
int fb=_find(b);
if(fa!=fb) f[fa]=fb;//已经建好的路放进一个集合
}
sort(po,po+k,cmp);//按照花费从小到大排序
printf("%d\n",kruskal());
}
}