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
输出样例:
12
#include<stdio.h>
#include<stdlib.h>
#define INFINITY 8888
struct Graph {
int** G;
int Nv;
int Ne;
};
typedef struct Graph* MyGraph;
void InitializeGraph(MyGraph Graph, int EdgeNum);
MyGraph Build_Graph(int N);
MyGraph Prim(MyGraph Graph,int*Flag);
int main()
{
int VertexNum;
int EdgeNum;
int Flag = 1;
scanf("%d %d", &VertexNum, &EdgeNum);
MyGraph Graph = Build_Graph(VertexNum);
InitializeGraph(Graph, EdgeNum);
MyGraph PrimGraph = Prim(Graph,&Flag);
if (Flag == 0)
{
printf("-1");
}
else
{
int Sum = 0;
for (int i = 1; i <= PrimGraph->Nv; i++)
{
for (int j = i + 1; j <= PrimGraph->Nv; j++)
{if(PrimGraph->G[i][j]!=INFINITY)
Sum = Sum + PrimGraph->G[i][j];
}
}
printf("%d", Sum);
}
}
MyGraph Build_Graph(int N)
{
MyGraph Graph = (MyGraph)malloc(sizeof(struct Graph));
Graph->G = (int**)malloc(sizeof(int*) * (N+1));
for (int i = 1; i < N + 1; i++)
{
Graph->G[i] = (int*)malloc(sizeof(int) * (N + 1));
}
for (int i = 1; i < N + 1; i++)
{
for (int j = 1; j < N + 1; j++)
{
if (i != j)
Graph->G[i][j] = INFINITY;
else
Graph->G[i][j] = 0;
}
}
Graph->Nv = N;
return Graph;
}
void InitializeGraph(MyGraph Graph, int EdgeNum)
{
int VertexA, VertexB, Weight;
for (int i = 0; i < EdgeNum; i++)
{
scanf("%d %d %d", &VertexA, &VertexB, &Weight);
Graph->G[VertexA][VertexB] = Weight;
Graph->G[VertexB][VertexA] = Weight;
}
Graph->Ne = EdgeNum;
}
MyGraph Prim(MyGraph Graph,int*Flag)
{
int StartVertex = 1;
MyGraph PrimGraph = Build_Graph(Graph->Nv);
int* Distance = (int*)malloc(sizeof(int) *( Graph->Nv+1));
int*Parent= (int*)malloc(sizeof(int) * (Graph->Nv + 1));//Parent是必要的,否则没法在新图里更新权重
int MinIndex = -1;
for (int i = 1; i <= Graph->Nv; i++)//初始化树到节点距离
{
Distance[i] = Graph->G[StartVertex][i];
if (Distance[i] != INFINITY)
{
Parent[i] = StartVertex;
}
}
while (1)
{
for (int i=0; i <= Graph->Nv; i++)
{
if ((Distance[i] > 0) && (Distance[i] < INFINITY) && (MinIndex == -1))
{
MinIndex = i;
}
else if ((Distance[i] > 0) && (Distance[i] < INFINITY) && (Distance[i] < Distance[MinIndex]))
{
MinIndex = i;
}
}
if (MinIndex == -1)
break;
else
{
Distance[MinIndex] = 0;
PrimGraph->G[Parent[MinIndex]][MinIndex] = Graph->G[Parent[MinIndex]][MinIndex];
PrimGraph->G[MinIndex][Parent[MinIndex]] = Graph->G[MinIndex][Parent[MinIndex]];
for (int i = 1; i <= Graph->Nv; i++)
{
if (Distance[i] > Graph->G[MinIndex][i])//不管是不是无穷都很方便地比较
{
Distance[i] = Graph->G[MinIndex][i];
Parent[i] = MinIndex;//可能是MinIndex也可能是后期更小的
}
}
}
MinIndex = -1;
}
for (int i = 1; i <= Graph->Nv; i++)
{
if (Distance[i] == INFINITY)
{
*Flag = 0;
}
}
return PrimGraph;
}