08-图7 公路村村通 (30 分)
作者:互联网
1 /* 图的邻接矩阵表示法 */ 2 #include <cstdio> 3 #include <stdlib.h> 4 5 #define MaxVertexNum 1001 /* 最大顶点数设为100 */ 6 #define INFINITY 65535 /* ∞设为双字节无符号整数的最大值65535*/ 7 #define ERROR -1 8 typedef int Vertex; /* 用顶点下标表示顶点,为整型 */ 9 typedef int WeightType; /* 边的权值设为整型 */ 10 11 12 /* 边的定义 */ 13 typedef struct ENode *PtrToENode; 14 struct ENode{ 15 Vertex V1, V2; /* 有向边<V1, V2> */ 16 WeightType Weight; /* 权重 */ 17 }; 18 typedef PtrToENode Edge; 19 20 /* 图结点的定义 */ 21 typedef struct GNode *PtrToGNode; 22 struct GNode{ 23 int Nv; /* 顶点数 */ 24 int Ne; /* 边数 */ 25 WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */ 26 }; 27 typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */ 28 29 30 31 32 33 /* 邻接点的定义 */ 34 typedef struct AdjVNode *PtrToAdjVNode; 35 struct AdjVNode{ 36 Vertex AdjV; /* 邻接点下标 */ 37 WeightType Weight; /* 边权重 */ 38 PtrToAdjVNode Next; /* 指向下一个邻接点的指针 */ 39 }; 40 41 /* 顶点表头结点的定义 */ 42 typedef struct Vnode{ 43 PtrToAdjVNode FirstEdge;/* 边表头指针 */ 44 } AdjList[MaxVertexNum]; /* AdjList是邻接表类型 */ 45 46 /* 图结点的定义 */ 47 typedef struct GNode2 *PtrToGNode2; 48 struct GNode2{ 49 int Nv; /* 顶点数 */ 50 int Ne; /* 边数 */ 51 AdjList G; /* 邻接表 */ 52 }; 53 typedef PtrToGNode2 LGraph; /* 以邻接表方式存储的图类型 */ 54 55 56 57 LGraph CreateGraph2( int VertexNum ) 58 { /* 初始化一个有VertexNum个顶点但没有边的图 */ 59 Vertex V; 60 LGraph Graph; 61 62 Graph = (LGraph)malloc( sizeof(struct GNode) ); /* 建立图 */ 63 Graph->Nv = VertexNum; 64 Graph->Ne = 0; 65 /* 初始化邻接表头指针 */ 66 /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */ 67 for (V=0; V<Graph->Nv; V++) 68 Graph->G[V].FirstEdge = NULL; 69 70 return Graph; 71 } 72 73 void InsertEdge2( LGraph Graph, Edge E ) 74 { 75 PtrToAdjVNode NewNode; 76 77 /* 插入边 <V1, V2> */ 78 /* 为V2建立新的邻接点 */ 79 NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode)); 80 NewNode->AdjV = E->V2; 81 NewNode->Weight = E->Weight; 82 /* 将V2插入V1的表头 */ 83 NewNode->Next = Graph->G[E->V1].FirstEdge; 84 Graph->G[E->V1].FirstEdge = NewNode; 85 86 /* 若是无向图,还要插入边 <V2, V1> */ 87 /* 为V1建立新的邻接点 */ 88 NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode)); 89 NewNode->AdjV = E->V1; 90 NewNode->Weight = E->Weight; 91 /* 将V1插入V2的表头 */ 92 NewNode->Next = Graph->G[E->V2].FirstEdge; 93 Graph->G[E->V2].FirstEdge = NewNode; 94 } 95 96 LGraph BuildGraph2() 97 { 98 LGraph Graph; 99 Edge E; 100 int Nv, i; 101 102 scanf("%d", &Nv); /* 读入顶点个数 */ 103 Graph = CreateGraph2(Nv); /* 初始化有Nv个顶点但没有边的图 */ 104 105 scanf("%d", &(Graph->Ne)); /* 读入边数 */ 106 if ( Graph->Ne != 0 ) { /* 如果有边 */ 107 E = (Edge)malloc( sizeof(struct ENode) ); /* 建立边结点 */ 108 /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */ 109 for (i=0; i<Graph->Ne; i++) { 110 scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 111 /* 注意:如果权重不是整型,Weight的读入格式要改 */ 112 InsertEdge2( Graph, E ); 113 } 114 } 115 116 117 return Graph; 118 } 119 120 121 Vertex FindMinDist( MGraph Graph, WeightType dist[] ) 122 { /* 返回未被收录顶点中dist最小者 */ 123 Vertex MinV, V; 124 WeightType MinDist = INFINITY; 125 126 for (V=0; V<Graph->Nv; V++) { 127 if ( dist[V]!=0 && dist[V]<MinDist) { 128 /* 若V未被收录,且dist[V]更小 */ 129 MinDist = dist[V]; /* 更新最小距离 */ 130 MinV = V; /* 更新对应顶点 */ 131 } 132 } 133 if (MinDist < INFINITY) /* 若找到最小dist */ 134 return MinV; /* 返回对应的顶点下标 */ 135 else return ERROR; /* 若这样的顶点不存在,返回-1作为标记 */ 136 } 137 138 int Prim( MGraph Graph) 139 { /* 将最小生成树保存为邻接表存储的图MST,返回最小权重和 */ 140 WeightType dist[MaxVertexNum], TotalWeight; 141 Vertex parent[MaxVertexNum], V, W; 142 int VCount; 143 Edge E; 144 145 /* 初始化。默认初始点下标是0 */ 146 for (V=0; V<Graph->Nv; V++) { 147 /* 这里假设若V到W没有直接的边,则Graph->G[V][W]定义为INFINITY */ 148 dist[V] = Graph->G[0][V]; 149 parent[V] = 0; /* 暂且定义所有顶点的父结点都是初始点0 */ 150 } 151 TotalWeight = 0; /* 初始化权重和 */ 152 VCount = 0; /* 初始化收录的顶点数 */ 153 154 /* 创建包含所有顶点但没有边的图。注意用邻接表版本 */ 155 LGraph MST = CreateGraph2(Graph->Nv); 156 E = (Edge)malloc( sizeof(struct ENode) ); /* 建立空的边结点 */ 157 158 /* 将初始点0收录进MST */ 159 dist[0] = 0; 160 VCount ++; 161 parent[0] = -1; /* 当前树根是0 */ 162 163 while (1) { 164 V = FindMinDist( Graph, dist ); 165 /* V = 未被收录顶点中dist最小者 */ 166 if ( V==ERROR ) /* 若这样的V不存在 */ 167 break; /* 算法结束 */ 168 169 /* 将V及相应的边<parent[V], V>收录进MST */ 170 E->V1 = parent[V]; 171 E->V2 = V; 172 E->Weight = dist[V]; 173 InsertEdge2( MST, E ); 174 TotalWeight += dist[V]; 175 dist[V] = 0; 176 VCount++; 177 178 for( W=0; W<Graph->Nv; W++ ) /* 对图中的每个顶点W */ 179 if ( dist[W]!=0 && Graph->G[V][W]<INFINITY ) { 180 /* 若W是V的邻接点并且未被收录 */ 181 if ( Graph->G[V][W] < dist[W] ) { 182 /* 若收录V使得dist[W]变小 */ 183 dist[W] = Graph->G[V][W]; /* 更新dist[W] */ 184 parent[W] = V; /* 更新树 */ 185 } 186 } 187 } /* while结束*/ 188 if ( VCount < Graph->Nv ) /* MST中收的顶点不到|V|个 */ 189 TotalWeight = ERROR; 190 return TotalWeight; /* 算法执行完毕,返回最小权重和或错误标记 */ 191 } 192 193 194 195 MGraph CreateGraph( int VertexNum ) 196 { /* 初始化一个有VertexNum个顶点但没有边的图 */ 197 Vertex V, W; 198 MGraph Graph; 199 200 Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */ 201 Graph->Nv = VertexNum; 202 Graph->Ne = 0; 203 /* 初始化邻接矩阵 */ 204 /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */ 205 for (V=0; V<Graph->Nv; V++) 206 for (W=0; W<Graph->Nv; W++) 207 Graph->G[V][W] = INFINITY; 208 209 return Graph; 210 } 211 212 void InsertEdge( MGraph Graph, Edge E ) 213 { 214 /* 插入边 <V1, V2> */ 215 Graph->G[E->V1][E->V2] = E->Weight; 216 /* 若是无向图,还要插入边<V2, V1> */ 217 Graph->G[E->V2][E->V1] = E->Weight; 218 } 219 220 MGraph BuildGraph() 221 { 222 MGraph Graph; 223 Edge E; 224 int Nv, i; 225 226 scanf("%d", &Nv); /* 读入顶点个数 */ 227 Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 228 229 scanf("%d", &(Graph->Ne)); /* 读入边数 */ 230 if ( Graph->Ne != 0 ) { /* 如果有边 */ 231 E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ 232 /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */ 233 for (i=0; i<Graph->Ne; i++) { 234 scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 235 E->V1--; E->V2--; 236 /* 注意:如果权重不是整型,Weight的读入格式要改 */ 237 InsertEdge( Graph, E ); 238 } 239 } 240 241 242 243 return Graph; 244 } 245 246 247 248 int main() { 249 MGraph Graph = BuildGraph(); 250 int res = Prim(Graph); 251 printf("%d\n", res); 252 253 }
标签:dist,struct,Graph,08,30,V1,顶点,Nv,村村通 来源: https://www.cnblogs.com/acoccus/p/10935704.html