Description
Input
Output
Sample Input
Sample Output
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,sum;
struct node
{
int start;///起点
int end;///终点
int power;///权值
} edge[5050];
int pre[5050];
int cmp(node a,node b)
{
return a.power<b.power;///按权值排序
}
int find(int x)///并查集找祖先
{
if(x!=pre[x])///递归法
{
pre[x]=find(pre[x]);
}
return pre[x];
/*int a;///循环法
a=x;
while(pre[a]!=a)
{
a=pre[a];
}
return a;*/
}
void merge(int x,int y,int n)
{
int fx =find(x);
int fy =find(y);
if(fx!=fy)
{
pre[fx]=fy;
sum+=edge[n].power;
}
}
int main()
{
int i,root;
while(scanf("%d%d",&m,&n)!=EOF)
{
if(m==0)
{
break;
}
sum=0;
for(i=1; i<=m; i++)
{
scanf("%d%d%d",&edge[i].start,&edge[i].end,&edge[i].power);
}
for(i=1; i<=m; i++) ///并查集的初始化
{
pre[i]=i;
}
sort(edge+1,edge+m+1,cmp);
for(i=1; i<=m; i++)
{
merge(edge[i].start,edge[i].end,i);
}
root=0;
for(i=1; i<=n; i++)///判断是否产生了生成树
{
if(pre[i]==i)
{
root++;
}
if(root>1)///如果根节点大于1说明没有产生最小生成树
{
break;
}
}
if(root>1)
{
printf("?\n");
}
else
{
printf("%d\n",sum);
}
}
return 0;
}
#include<stdio.h>
#include<string.h>
#define MAX 0x3f3f3f3f
using namespace std;
int logo[1010];///用0和1来表示是否被选择过
int map1[1010][1010];
int dis[1010];///记录任意一点到这一点的最近的距离
int n,m;
int prim()
{
int i,j,now;
int sum=0;
for(i=1;i<=n;i++)///初始化
{
dis[i]=MAX;
logo[i]=0;
}
for(i=1;i<=n;i++)
{
dis[i]=map1[1][i];
}
dis[1]=0;
logo[1]=1;
for(i=1;i<n;i++)///循环查找
{
now=MAX;
int min1=MAX;
for(j=1;j<=n;j++)
{
if(logo[j]==0&&dis[j]<min1)
{
now=j;
min1=dis[j];
}
}
if(now==MAX)///防止不成图
{
break;
}
logo[now]=1;
sum=sum+min1;
for(j=1;j<=n;j++)///填入新点后更新最小距离
{
if(logo[j]==0&&dis[j]>map1[now][j])
{
dis[j]=map1[now][j];
}
}
}
if(i<n)
{
printf("?\n");
}
else
{
printf("%d\n",sum);
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)///n是点数
{
if(m==0)
{
break;
}
memset(map1,0x3f3f3f3f,sizeof(map1));///map是邻接矩阵储存图的信息
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(c<map1[a][b])///防止出现重边
{
map1[a][b]=map1[b][a]=c;
}
}
prim();
}
return 0;
}
Description
Input
Output
Sample Input
Sample Output
Hint
Hint Huge input, scanf is recommended.
///克鲁斯卡尔算法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,sum;
struct node
{
int start;///起点
int end;///终点
int power;///权值
}edge[5050];
int pre[5050];
int cmp(node a,node b)
{
return a.power<b.power;///按权值排序
}
int find(int x)///并查集找祖先
{
if(x!=pre[x])///递归法
{
pre[x]=find(pre[x]);
}
return pre[x];
/*int a;///循环法
a=x;
while(pre[a]!=a)
{
a=pre[a];
}
return a;*/
}
void merge(int x,int y,int n)
{
int fx =find(x);
int fy =find(y);
if(fx!=fy)
{
pre[fx]=fy;
sum+=edge[n].power;
}
}
int main()
{
int i;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
break;
}
sum=0;
m=n*(n-1)/2;//边数
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].start,&edge[i].end,&edge[i].power);
}
for(i=1;i<=m;i++)///并查集的初始化
{
pre[i]=i;///每一个点的祖先都是自己
}
sort(edge+1,edge+m+1,cmp);
for(i=1;i<=m;i++)
{
merge(edge[i].start,edge[i].end,i);
}
printf("%d\n",sum);
}
return 0;
}
///普里姆算法
#include<stdio.h>
#include<string.h>
#define MAX 0x3f3f3f3f
using namespace std;
int logo[1010];///用0和1来表示是否被选择过
int map1[1010][1010];
int dis[1010];///记录任意一点到这一点的最近的距离
int n,m;
int prim()
{
int i,j,now;
int sum=0;
for(i=1; i<=n; i++) ///初始化
{
dis[i]=MAX;
logo[i]=0;
}
for(i=1; i<=n; i++)///任意一个点到第一个点的距离
{
dis[i]=map1[1][i];
}
dis[1]=0;
logo[1]=1;///第一个点已经被访问过,加入可选顶点集
for(i=1; i<n; i++)
{
now=MAX;
int min1=MAX;
for(j=1; j<=n; j++)///再找到一条以可选顶点集里为顶点的一条边
{
if(logo[j]==0&&dis[j]<min1)
{
now=j;
min1=dis[j];
}///循环查找最小值
}
if(now==MAX)///防止不成图
{
break;
}
logo[now]=1;
sum=sum+min1;
for(j=1; j<=n; j++) ///填入新点后更新最小距离,剩余各点到可选顶点集的距离
{
if(logo[j]==0&&dis[j]>map1[now][j])
{
dis[j]=map1[now][j];
}
}
}
printf("%d\n",sum);
}
int main()
{
while(scanf("%d",&n)!=EOF)///n是点数
{
if(n==0)
{
break;
}
m=n*(n-1)/2l;
memset(map1,0x3f3f3f3f,sizeof(map1));///map是邻接矩阵储存图的信息
for(int i=0; i<m; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(c<map1[a][b])///防止出现重边
{
map1[a][b]=map1[b][a]=c;
}
}
prim();
}
return 0;
}
原文:https://www.cnblogs.com/wkfvawl/p/9239135.html