数据结构:公路村村通(Prim算法)30分

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数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 1001
#define MaxInt 3000
int fcost=0;//最终成本
int flag=0;//是否连通的标记
struct edge{//当前点
    int adjvex;//上一个点
    int lowcost;//此点到未记录点的最短距离
}closedge[Max];
typedef struct{
    int vexs[Max];//各村的信息
    int arcs[Max][Max];//各村之间的路
    int vexnum,arcnum;
}AMGraph;
void CreateAMGraph(AMGraph &G){//创建一连通图
    int N,M;
    scanf("%d%d",&N,&M);
    G.vexnum=N;
    G.arcnum=M;
    for(int i=1;i<=N;i++){
        G.vexs[i]=i;
    }
    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            if(i==j){
                 G.arcs[i][j]=0;
                 G.arcs[j][i]=0;
            }

            else{
                 G.arcs[i][j]=MaxInt;
                 G.arcs[j][i]=MaxInt;
                 //将不存在的路径设为最大值
            }

        }
    }
    for(int i=0;i<M;i++){
        int x1,x2,x3;
    scanf("%d%d%d",&x1,&x2,&x3);
    G.arcs[x1][x2]=x3;
    G.arcs[x2][x1]=x3;
    }
}
int Min(AMGraph G){//找出当前点到各未标记点的最小距离并返回坐标
    int minpath=MaxInt;
    int minv=0;
    for(int i=1;i<=G.vexnum;i++){
        if(closedge[i].lowcost!=0){//已经记录的点无需再找,否则影响结果
                if(closedge[i].lowcost<minpath){
                    minpath=closedge[i].lowcost; //此点的最小路径为表格中最小的点
                    minv=i;//记录该点
                }
        }
    }
    if(minv==0){//没找到最小点,说明不连通
        flag=1;
    }
    fcost+=minpath;//把各步找到的最短路径都加起来
            return minv;

}
void Prim(AMGraph G,int u){//普利姆算法求出最小生成树
    closedge[u].lowcost=0;//标记第一个点
    for(int i=1;i<=G.vexnum;i++){
        if(i!=u){
            closedge[i].adjvex=u;
            closedge[i].lowcost=G.arcs[u][i];//起始点到各未标记点的路程
        }
    }
    for(int i=1;i<G.vexnum;i++){
        int x=Min(G);//从最近的点开始找下一个点
        closedge[x].lowcost=0;//不要忘记给此点最短距离赋值为零
        for(int j=1;j<G.vexnum;j++){
            if(G.arcs[x][j]<closedge[j].lowcost){//更新最短距离
                closedge[j].adjvex=G.vexs[x];//上一个点更新
                closedge[j].lowcost=G.arcs[x][j];
            }
        }
    }
}
int main(){
    AMGraph G;
    CreateAMGraph(G);
    Prim(G,1);
    if(flag==1)
        printf("%d",-1);
    else
        printf("%d",fcost);
    return 0;
}

### PTA平台上的村村通问题及其Prim算法解题思路 #### 题目描述 在一个给定的无向加权图中,有`N`个节点代表村庄以及`M`条边表示可能建设的道路。目标是从这些道路中选出一些构建最小生成树(MST),使得所有村庄都能连通,并使总成本最低。 #### 输入说明 输入的第一行提供两个整数`N`(1 ≤ N ≤ 20) 和 `M`,别指代村庄数量和计划修筑的道路总数。随后的每一行包含三个正整数,依次为连接两座不同村庄i, j之间的路径代价cij[^2]。 #### 解决方案概述 为了找到最优解决方案,可以运用贪心策略下的经典图论算法——Prim算法来计算最小生成树。此方法通过逐步扩展已有的部树直到覆盖整个网络,在每次迭代过程中总是挑选当前可用最短的一条边加入现有集合内[^3]。 #### Python实现细节 下面是一个基于Python语言的具体编码实例: ```python import heapq def prim_algorithm(N, edges): graph = [[] for _ in range(N)] # 构建邻接表形式的图结构 for u, v, w in edges: graph[u-1].append((v-1, w)) graph[v-1].append((u-1, w)) visited = set() min_heap = [(0, 0)] # 初始堆栈设置起点权重为零 total_cost = 0 while len(visited) < N and min_heap: weight, node = heapq.heappop(min_heap) if node not in visited: visited.add(node) total_cost += weight for neighbor, edge_weight in graph[node]: if neighbor not in visited: heapq.heappush(min_heap, (edge_weight, neighbor)) return "Total Cost of MST:" + str(total_cost) if len(visited)==N else 'Impossible' ``` 这段代码首先创建了一个空列表用于存储各个节点相连的信息;接着读取输入中的每一条记录并填充至对应的子列表里形成完整的图形模型;最后利用优先队列实现了经典的Prim算法逻辑流程[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值