公路村村通
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
具体思路
最小生成树的生成,普利姆算法,还可以用另一种,都一样简单
具体代码
#include<stdio.h>
#include<stdlib.h>
#define MAX 1000
#define BKD 65535
#define ERROR -1
#define false -1
#define true 1
typedef struct node *Post;
struct node
{
int ding;
int bian;
int m[MAX][MAX];
};
typedef Post Mgraph;/*邻接矩阵储存图*/
int dist[MAX];/*普利姆算法的储存数组*/
int dao=0;/*纳入最小生成树的顶点个数*/
Mgraph JIANtu()/*建图*/
{
Mgraph M;
M=(Mgraph)malloc(sizeof(struct node));
int b,d,i,j,zh,a;
scanf("%d",&M->ding);
for( i=0;i<M->ding;i++)
for( j=0;j<M->ding;j++)
{
M->m[i][j]=BKD;/*边的初始化要为足够大的数*/
}
scanf("%d",&M->bian);
for(i=0;i<M->bian;i++)
{
scanf("%d %d %d",&b,&d,&zh);
M->m[b-1][d-1]=zh;/*无向图*/
M->m[d-1][b-1]=zh;
}
return M;
}
int Findmin(Mgraph M,int dist[])/*类似迪杰斯特拉算法的找出,dist值最小的哪一个。但是有点出入,直接用dist来标记是否访问*/
{
int mv,i;
int md=BKD;
for(i=0;i<M->ding;i++)
{
if(dist[i]!=0&&dist[i]<md)
{
md=dist[i];
mv=i;
}
}
if(md<BKD)
{
return mv;
}
else
return ERROR;
}
int Prim(Mgraph M)/*普利姆算法,返回最小生成树的总权重*/
{
int i,j,k;
int qi=0;
for(i=0;i<M->ding;i++)
{
if(M->m[0][i]<BKD)/*一般都是从0这个顶点开始的,从其他点,可以更换*/
dist[i]=M->m[0][i];/*初始这个dist数组*/
else
dist[i]=BKD;
}
dao++;/*起点进去了,加一*/
dist[0]=0;/*变为0,标识已经纳入最小生成树中了*/
while(1)
{
i=Findmin(M,dist);
if(i==ERROR)/*找不出来就结束循环了*/
break;
dao++;/*找出来一个,顶点个数就加一*/
qi+=dist[i];/*计算权重*/
dist[i]=0;/*标记已经访问*/
for(j=0;j<M->ding;j++)/*替换,找到可以到的路径,就标识出来长度*/
{
if(dist[j]!=0&&M->m[i][j]<BKD)/*必须是没用访问过的顶点*/
{
if(M->m[i][j]<dist[j])
{
dist[j]=M->m[i][j];
}
}
}
}
return qi;
}
int main()
{
Mgraph M;
M=JIANtu();
int k;
k=Prim(M);
if(dao!=M->ding)/*当进入最小生成树的顶点个数不等于图的顶点数时,说明图不连通*/
printf("-1");
else
printf("%d",k);
}
具体结果![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8238bcc703cad66618d446531f34a27a.png)
代码很基础,有错请指出,一起进步,谢谢!