八、图(下):公路村村通

2023-12-30 14:58
文章标签 公路 村村通

本文主要是介绍八、图(下):公路村村通,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 题目描述
  • 代码
  • 解题思路和出现的问题

题目描述

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

输入格式:
输入数据包括城镇数目正整数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<stdbool.h>
#include<malloc.h>
#define MaxVerteNum 1000
typedef int Vertex;
typedef int WeightType; typedef struct ENode *PtrToENode;
struct ENode{WeightType Weight;Vertex V1;Vertex V2;
};
typedef PtrToENode Edge;typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{PtrToAdjVNode Next;Vertex AdjV;WeightType Weight; /* 存储边的权重 */
};typedef struct HNode{PtrToAdjVNode FirstEdge;
}AdjList[MaxVerteNum];typedef struct LNode *LGraph;
struct LNode{int Nv;int Ne;AdjList G;
};LGraph Create( int VertexNum )
{Vertex V;LGraph Graph;Graph = (LGraph)malloc(sizeof(struct LNode));Graph->Nv = VertexNum;Graph->Ne = 0;for( V=0; V!=VertexNum; ++V )Graph->G[V].FirstEdge = NULL;return Graph;
}void InsertEdge( LGraph Graph, PtrToENode E )
{PtrToAdjVNode NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode->AdjV = E->V2;NewNode->Weight = E->Weight;NewNode->Next = Graph->G[E->V1].FirstEdge;Graph->G[E->V1].FirstEdge = NewNode;NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));NewNode->AdjV = E->V1;NewNode->Weight = E->Weight;NewNode->Next = Graph->G[E->V2].FirstEdge;Graph->G[E->V2].FirstEdge = NewNode;
}LGraph BuildGraph()
{LGraph Graph;PtrToENode E;Vertex V;int Nv, i;scanf("%d",&Nv);Graph = Create(Nv);scanf("%d",&(Graph->Ne));if(Graph->Ne){E = (PtrToENode)malloc(sizeof(struct ENode));for(i=0;i<Graph->Ne;++i){scanf("\n%d %d %d",&E->V1,&E->V2,&E->Weight);--E->V1;--E->V2;InsertEdge( Graph, E );}}return Graph;
}/* -----------顶点并查集定义----------- */
typedef Vertex ElementType; /* 元素类型 */
typedef Vertex SetName; /* 根结点下标作为集合名称 */
typedef ElementType SetType[MaxVerteNum];void InitializeVSet( SetType S, int N )
{ElementType X;for ( X=0; X!=N; ++X )S[X] = -1;
}void Union( SetType S, SetName Root1, SetName Root2 )
{/* 小集合并入大集合 */if ( S[Root1] < S[Root2] ){S[Root2] += S[Root1]; /* 集合1并入集合2 */S[Root1] = Root2;}else {S[Root1] += S[Root2];S[Root2] = Root1;}
}SetName Find( SetType S, ElementType X )
{ /* 集合元素已经全部初始化为-1 */if ( S[X] < 0 ) /* 找到集合的根 */return X;elsereturn S[X] = Find( S, S[X] ); /* 路径压缩 */
}bool CheckCycle( SetType VSet, Vertex V1, Vertex V2 )
{Vertex Root1, Root2;Root1 = Find( VSet, V1 ); /* 得到V1所属的连通集名称 */Root2 = Find( VSet, V2 ); /* 得到V2所属的连通集名称 */if ( Root1 == Root2 )return false;else {Union( VSet, Root1, Root2 );return true;}
}
/*-----------并查集定义结束--------------*//*-----------边的最小堆定义--------------*/
void PerDown( Edge ESet, int p, int N )
{/* 假设含有N个元素的边数组中,以ESet[p]为根结点的左右子堆都是最小堆 *//* 将ESet[p]为根结点的堆调整为最小堆 */int Parent, Child;struct ENode X;X = ESet[p];for( Parent = p; (Parent*2+1)<N; Parent=Child ){Child = Parent * 2 + 1;if( (Child!=N-1) && (ESet[Child].Weight>ESet[Child+1].Weight) )++Child;if( X.Weight <= ESet[Child].Weight )break;elseESet[Parent] = ESet[Child];}ESet[Parent] = X;
}void InitializeESet ( LGraph Graph, Edge ESet )
{ /* 将图的边存入数组ESet,并且初始化为最小堆 */Vertex V;PtrToAdjVNode W;int ECount;/* 将图的边存入数组ESet */ECount = 0;for( V=0; V<Graph->Nv; ++V )for ( W=Graph->G[V].FirstEdge; W; W=W->Next )if( V < W->AdjV ){ESet[ECount].V1 = V;ESet[ECount].V2 = W->AdjV;ESet[ECount++].Weight = W->Weight;}/* 初始化为最小堆 */for( ECount = Graph->Ne/2-1;ECount>=0;--ECount )PerDown(ESet, ECount, Graph->Ne);
} void Swap( PtrToENode E1, PtrToENode E2 )
{struct ENode ETemp;ETemp = *E2;*E2 = *E1;*E1 = ETemp;
}int GetEdge(Edge ESet, int CurrentSize)
{ /* 给定当前堆的大小CurrentSize,将当前最小边位置弹出并调整堆 */Swap( &ESet[0],&ESet[CurrentSize-1] );PerDown( ESet, 0, CurrentSize-1 );return CurrentSize - 1;
}
/* ------------边的最小堆定义结束--------------- */int Kruskal( LGraph Graph, LGraph MST )
{WeightType TotalWeight;int ECount, NextEdge;SetType VSet;Edge ESet;InitializeVSet( VSet, Graph->Nv ); /* 初始化顶点并查集,每个顶点都是一个集合,根结点是自己 */ESet = (Edge)malloc(sizeof(struct ENode)*Graph->Ne);InitializeESet( Graph, ESet ); /* 初始化边的最小堆 *//* 定义一个新的图用来存储最小生成树 */MST = Create(Graph->Nv);TotalWeight = 0;ECount = 0;NextEdge = Graph->Ne; /* 原始的边的集合的规模,也就是最小堆的规模 */while ( ECount < Graph->Nv-1 ){/* 构成树的边数应该恰好等于Graph->Nv-1 */NextEdge = GetEdge(ESet, NextEdge); /* 获得Weight最小的边的位置,并且这个位置也作为新的最小堆的规模 */if( NextEdge == 0 ) /* 边集中没有边了 */break;/* 如果该边的加入不构成回路,即两端结点不属于同一连通集 */if ( CheckCycle( VSet, ESet[NextEdge].V1, ESet[NextEdge].V2 )){/* 将该边插入MST */InsertEdge( MST, ESet+NextEdge );TotalWeight += ESet[NextEdge].Weight;/* 累计权重 */++ECount;}}if( ECount < Graph->Nv-1 ) /* 边集中没有边了,从while循环中跳出 */TotalWeight = -1; /* 设置错误标记,表示生成树不存在 */return TotalWeight;
}int main()
{LGraph Graph = BuildGraph();LGraph MST;int TotalWeight = Kruskal( Graph, MST );printf("%d", TotalWeight);return 0;
}

解题思路和出现的问题

1.建立图,把边和顶点都储存在图中。
2.所有边储存在最小堆中,这样是方便每次取出Weight最小的边。
3.取出Weight最小的边,重新整理最小堆。看如果这条边插入生成树中会不会有回路(方法是利用并查集)

出现的问题主要是在最小堆里面,最小堆储存的是边不是顶点,所以调用下滤函数PerDown(ESet, ECount, Graph->Ne);这里不能写成Graph->Nv。以后每次写完一个函数都要检查一下变量是不是对的,否则出错了要从头到尾检查太慢了。

这篇关于八、图(下):公路村村通的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/553209

相关文章

06-3. 公路村村通(30) 最小生成树

06-3. 公路村村通(30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。 输入格式说明: 输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<

智慧公路大数据运营中心整体解决方案

方案简介: 智慧公路大数据运营中心解决方案的实施,不仅提高了公路交通的运行效率和管理水平,还推动了智慧交通建设的深入发展。通过消除信息孤岛、促进数据共享和开放,实现了交通信息资源的有效整合和利用。未来,随着技术的不断进步和应用的不断深化,智慧公路大数据运营中心将在更多领域发挥重要作用,为构建安全、高效、绿色的现代交通体系贡献力量。 部分方案内容:

06-3. 公路村村通(30)

06-3. 公路村村通(30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。 输入格式说明: 输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<=3N

公路气象站的基本功能是什么

在快速发展的现代交通网络中,公路气象站扮演着重要角色。公路气象站通过实时监测和传输道路气象条件数据,为公路管理、交通管理和驾驶员提供了及时、准确的气象信息,有效提升了公路的通行效率和安全性。 公路气象站的基本功能 公路气象站通常安装在公路或高速公路附近,配备有各种气象传感器和设备,能够实时监测和记录多种气象参数,包括温度、湿度、风速、风向、降雨量以及能见度等。这些数据对于评估道路状况、

中国最美公路

中国最美公路 《中国国家地理》2021年增刊 文章目录 中国最美公路横断山地公路绿洲荒漠公路天山山地公路秦巴公路黄土高原公路东部滨海公路林海雪原公路东南丘陵公路喀斯特公路青藏高原公路致敬最美长线公路极致公路 横断山地公路 214国道 215国道 227国道 绿洲荒漠公路 315国道——西宁至喀什 216国道(塔克拉玛干沙漠公路) G7京新高速 天山山地公

【免费分享】全国shp数据汇总(中国湖泊、县界、公路、河流、铁路、国界线、经纬线、省会城市、省级行政区、县城驻地、线状省界)

ESRI Shapefile(shp),或简称shapefile,该文件格式已经成为了地理信息软件界的开放标准,也是重要的交换格式,能够在ESRI与其他公司的产品之间进行数据互操作。 Shapefile属于一种矢量图形格式,它能够保存几何图形的位置及相关属性。用于描述几何体对象:点、折线与多边形。例如,Shapefile文件可以存储井、河流、湖泊等空间对象的几何位置。除了几何位置,shp文件

【洛谷】P1111:修复公路

闲来无事找个题目(做完后才想到写个博客,所以图片是后来拍的): 哇,是个并查集的题诶。 怀揣着好奇心,我点进去看了看。 题目 传送门 我随手打开csacademy,建了个图。怎样才能让任意两个村庄都存在至少一条修复完成的路呢?我想了想,惊讶地发现这道题十分简单。 任意两节点都存在一条路,那就是树,要从图中扣树,图又是无向图,那不就是最小生成树嘛。 所以,这道题就是个模板题。

【最小生成树Kruskal】【并查集】乡村公路

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 21   Accepted Submission(s) : 10 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的

HSACM 1503 公路乘车

1503: 公路乘车 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 21   Solved: 13   Scores: 89.83 [ Submit][ Status][ BBS] Description 一个特别的单行街道在每公里处有一个汽车站。顾客根据他们乘坐汽车的公里使来付费。例如下表就是一个费用的单子。   没有一辆车子

修复公路[并查集结构体]

修复公路 题目背景 A 地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。 题目描述 给出 A 地区的村庄数 N N N,和公路数 M M M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。 输入格式