题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数 �,� N, M,表示该图共有 � N 个结点和 � M 条无向边。
接下来 � M 行每行包含三个整数 ��,��,�� Xi, Yi, Zi,表示有一条长度为 �� Zi 的无向边连接结点 ��,�� Xi, Yi。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
输入输出样例
输入 #1复制
4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3
输出 #1复制
7
说明/提示
数据规模:
对于 20%20% 的数据,�≤5 N≤5,�≤20 M≤20。
对于 40%40% 的数据,�≤50 N≤50,�≤2500 M≤2500。
对于 70%70% 的数据,�≤500 N≤500,�≤104 M≤104。
对于 100%100% 的数据:1≤�≤50001≤ N≤5000,1≤�≤2×1051≤ M≤2×105,1≤��≤1041≤ Zi≤104。
样例解释:
所以最小生成树的总边权为 2+2+3=72+2+3=7。
该题可以采用kruscal和prim两种算法。
prim算法:
首先,以任意节点作为根节点,找出与之相邻的边。再将新节点更新并且以此节点作为根继续搜。用disl数组来记录已用点到未用点的最短距离。
kruscal算法:
先把边按照权值进行从小到大排序,每一次优先选取权值较小的边,判断他们连接的话是否会出现环,如果出现就跳过这条边(用并查集)继续搜索,直到进行边数次。
代码实现:
prim:
#include"stdio.h"
#define N 5005
#define M 200005
int e[N][N],dis[N],book[N];
main()
{
int n,m;
int x,y,z,i,j,k;
int sum=0,min=0,count=0;
int inf=119999999;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j) e[i][j]=0;
else e[i][j]=inf;
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
e[x][y]=z;
e[y][x]=z;
}
for(i=1;i<=n;i++)
dis[i]=e[1][i];
book[1]=1;
count++;
while(count<n)
{
min=inf;
for(i=1;i<=n;i++)
{
if(book[i]==0&&dis[i]<min)
{
min=dis[i];
j=i;
}
}
book[j]=1;
count++;
sum+=dis[j];
for(k=1;k<=n;k++)
{
if(book[k]==0&&dis[k]>e[j][k])
dis[k]=e[j][k];
}
}
printf("%d",sum);
}
kruscal:
#include"stdio.h"
#define N 5005
#define M 200005
int dis[N],book[N],n,m;
struct s
{
int x;
int y;
int z;
}e[N];
int find(int v)
{
if(book[v]==v) return v;
else
{
book[v]=find(book[v]);
return book[v];
}
}
int hb(int v,int u)
{
int t1,t2;
t1=find(v);
t2=find(u);
if(t1!=t2)
{
book[t2]=t1;
return 1;
}
return 0;
}
int sort(int left,int right)
{
if(left>=right) return 0;
int i=left,j=right;
struct s k,t=e[left];
while(i<j)
{
while(i<j&&t.z<=e[j].z) j--;
while(i<j&&t.z>=e[i].z) i++;
if(i<j)
{
t=e[i];e[i]=e[j];e[j]=t;
}
}
e[left]=e[i];
e[i]=t;
sort(left,i-1);
sort(i+1,right);
}
int fun()
{
int i,j,sum=0,count;
for(i=0,count=1;i<m;i++)
{
{
if(hb(e[i].x,e[i].y))
{
count++;
sum+=e[i].z;
}
if(count>=n) break;
}
if(i>=m) return -1;
return sum;
}
}
main()
{
int i,j,k;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
book[i]=i;
for(i=0;i<m;i++)
{
scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].z);
}
sort(0,m-1);
k=fun();
if(k==-1) printf("orz\n");
else printf("%d\n",k);
}