D e s c r i p t i o n Description Description
学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们之间有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,你的任务是使任意两台计算机都连通(不管是直接的或间接的)。
I n p u t Input Input
第一行为整数n(2<=n<=100),表示计算机的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台计算机和第y台计算机的费用。
O u t p u t Output Output
一个整数,表示最小的连接费用。
S a m p l e I n p u t Sample Input SampleInput
3
0 1 2
1 0 1
2 1 0
S a m p l e O u t p u t Sample Output SampleOutput
2
注:表示连接1和2,2和3,费用为2)
思路
2019.4.25.今天有事,思路明天再写,先放代码
P r i m Prim Prim思路
从
1
1
1开始找
1
1
1能够到达的且距离最短的点
然后更新到其他没到达的点的距离
再找没有到达过的且距离最短的点
如此循环……
P r i m Prim Prim邻接矩阵
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 10000
using namespace std;
int F[225][225],B[225],K[225];
//F代表两点距离
//B表示有没有到达过
//K表示当前离每个点的最短距离
int Ans,n,m,x,y;
int main()
{
scanf("%d",&n);
memset(F,0x3f,sizeof(F));
memset(K,0x3f,sizeof(K));
memset(B,0,sizeof(B));
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&F[i][j]);
K[1]=0;//
for(int i=1;i<=n;++i)
{
int k=0;
for(int j=1;j<=n;++j)
if(!B[j] && K[k]>K[j])k=j;//如果没到达且距离比当前点的距离小
B[k]=1,Ans+=K[k];//加上距离且判定为到过
for(int j=1;j<=n;++j)
if(!B[j])K[j]=min(F[k][j],K[j]);//更新还没到过的点的最短距离
}
printf("%d",Ans);
return 0;
}
P r i m Prim Prim邻接表
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 10000
using namespace std;
int B[225],K[225],h[225];
int Ans,n,m,t,tot;
struct whw
{
int w,x,h;
}wh[20025];
void hw(int x,int y,int s)
{
wh[++tot]=(whw){y,s,h[x]};h[x]=tot;
wh[++tot]=(whw){x,s,h[y]};h[y]=tot;
}
int main()
{
scanf("%d",&n);
memset(K,0x3f,sizeof(K));
memset(B,0,sizeof(B));
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
scanf("%d",&t);
if(i<j)hw(i,j,t);
}
K[1]=0;
for(int i=1;i<=n;++i)
{
int k=0;
for(int j=1;j<=n;++j)
if(!B[j] && K[k]>K[j])k=j;
B[k]=1,Ans+=K[k];
for(int j=h[k];j;j=wh[j].h)
//与邻接矩阵最主要的区别。到达一个点,只可能更新与此相连的点的最短距离
if(!B[wh[j].w])K[wh[j].w]=min(wh[j].x,K[wh[j].w]);
}
printf("%d",Ans);
return 0;
}
K r u s k a l Kruskal Kruskal思路
因为求得是最小的边和
所以我们就把边排序
然后对边进行判断
如果不在一个集合里的话
就放在一起
注:
这里用到了并查集
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct whw
{
int x,s,y;
}wh[100025];
int n,t,k,x,y;
long long Ans;
int Fa[225];
int Find(int k)//并查集
{
while(Fa[k]!=k)k=Fa[k];
return k;
}
bool Cmp(whw i,whw j)//从小到大
{return i.s<j.s;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
scanf("%d",&k);
if(i<j)wh[++t].x=i,//因为有重复的,所以只用建一半的边
wh[t].s=k,wh[t].y=j;
}
sort(wh+1,wh+t+1,Cmp);
for(int i=1;i<=n;++i)Fa[i]=i;
for(int i=1;i<=t;++i)
{
x=Find(wh[i].x);
y=Find(wh[i].y);
if(x!=y)//判断是否在一个集合
{
Fa[max(x,y)]=Fa[min(x,y)];
Ans=Ans+(long long)wh[i].s;
}
}
printf("%lld",Ans);
return 0;
}