08-图7 公路村村通 (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
// ss66.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 1001
#define M 3003
#define max 65535
typedef struct enode *polynomial;
struct enode
{
int v1,v2;
int weight;
};
typedef polynomial edge;
typedef struct gnode *polynode;
struct gnode
{
int nv,ev;
int g[N][N];
};
typedef polynode mgraph;
mgraph buildgraph (int n,int m);
mgraph craetegraph(int n);
void Prim( mgraph graph);
void insert(edge e,mgraph graph);
int main(void)
{
int n,m;
scanf("%d %d",&n,&m);
mgraph graph = buildgraph(n,m);
Prim(graph);
return 0;
}
mgraph buildgraph (int n,int m)
{
mgraph graph;
graph = craetegraph(n);
int i;
edge e;
if(n != 0)
e = (edge)malloc(sizeof(struct enode));
for(i = 0;i < m;i++)
{
scanf("%d %d %d",&e->v1,&e->v2,&e->weight);
insert(e,graph);
}
return graph;
}
mgraph craetegraph(int n)
{
mgraph graph;
graph = (mgraph)malloc(sizeof(struct gnode));
graph->nv = n;
graph->ev = 0;
int i,j;
for(i = 0;i < n ;i++)
for(j = 0;j < n ;j++)
graph->g[i][j] = max;
return graph;
}
void insert(edge e,mgraph graph)
{
graph->g[e->v1 - 1][e->v2 - 1] = e->weight;
graph->g[e->v2 - 1][e->v1 - 1] = e->weight;
}
int FindMinDist( mgraph graph, int dist[] )
{ /* 返回未被收录顶点中dist最小者 */
int min,v;
int MinDist = max ;
for (v = 0; v < graph->nv; v++) {
if ( dist[v] != 0 && dist[v] < MinDist) {
/* 若V未被收录,且dist[V]更小 */
MinDist = dist[v]; /* 更新最小距离 */
min = v; /* 更新对应顶点 */
}
}
if (MinDist < max) /* 若找到最小dist */
return min; /* 返回对应的顶点下标 */
else return -1; /* 若这样的顶点不存在,返回-1作为标记 */
}
void Prim( mgraph graph)
{ /* 将最小生成树保存为邻接表存储的图MST,返回最小权重和 */
int dist[N], TotalWeight;
int parent[N], V, W;
int VCount;
// edge E;
/* 初始化。默认初始点下标是0 */
for (V=0; V < graph->nv; V++) {
/* 这里假设若V到W没有直接的边,则Graph->G[V][W]定义为INFINITY */
dist[V] = graph->g[0][V];//初始为max值;
parent[V] = 0; /* 暂且定义所有顶点的父结点都是初始点0 */
}//初始化
TotalWeight = 0; /* 初始化权重和 */
VCount = 0; /* 初始化收录的顶点数 */
/* 创建包含所有顶点但没有边的图。注意用邻接表版本 */
// MST = CreateGraph(graph->nv);
// E = (edge)malloc( sizeof(struct enode) ); /* 建立空的边结点 */
/* 将初始点0收录进MST */
dist[0] = 0;
VCount ++;
parent[0] = -1; /* 当前树根是0 */
while (1) {
V = FindMinDist( graph, dist );
/* V = 未被收录顶点中dist最小者 */
if ( V == -1) /* 若这样的V不存在 */
break; /* 算法结束 */
/* 将V及相应的边<parent[V], V>收录进MST */
// E->v1 = parent[V];
// E->v2 = V;
// E->weight = dist[V];
// InsertEdge( MST, E );
TotalWeight += dist[V];
dist[V] = 0;
VCount++;
for( W = 0; W < graph->nv; W++ ) /* 对图中的每个顶点W */
if ( dist[W] != 0 && graph->g[V][W] < max ) {
/* 若W是V的邻接点并且未被收录 */
if ( graph->g[V][W] < dist[W] ) {
/* 若收录V使得dist[W]变小 */
dist[W] = graph->g[V][W]; /* 更新dist[W] */
parent[W] = V; /* 更新树 */
}
}
} /* while结束*/
if ( VCount < graph->nv ) /* MST中收的顶点不到|V|个 */
TotalWeight = -1;
printf("%d\n",TotalWeight);
}