问题 R: 自来水管道
时间限制: 1 Sec 内存限制: 128 MB
提交: 840 解决: 241
[提交][状态][讨论版]
题目描述
你领到了一个铺设校园内自来水管道的任务。校园内有若干需要供水的点,每两个供水点可能存在多种铺设路径。对于每一种铺设路径,其成本是预知的。
任务要求最终铺设的管道保证任意两点可以直接或间接的联通,同时总成本最低。
输入
每个测试用例由多行组成,第一行是两个整数P和R,P代表供水点数(1<=P<=50),每个点都对应1到P中的一个唯一编号。R代表可能的铺设路径数,路径数可能有非常多。接下有R行,每行格式如下:
节点A编号 节点B编号 路径成本
路径成本不超过100。
测试用例之间有一空行分开。输入结束用P=0表示,注意没有R值。
输出
每个测试用例占用一行输出最低总成本。
样例输入
1 0
2 3
1 2 37
2 1 17
1 2 68
3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32
5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12
0
样例输出
0
17
16
26
分析:典型的prim算法,求最小生成树,把邻接矩阵构造好,就OK了。
#include<stdio.h>
#define max 1e7
#define MAXCOST 1e7
#define MAX 100
int Prim(int graph[MAX][MAX],long long int n)
{
/* lowcost[i]记录以i为终点的边的最小权值,当lowcost[i]=0时表示终点i加入生成树 */
int lowcost[MAX];
/* mst[i]记录对应lowcost[i]的起点 */
int mst[MAX];
int i, j, min, minid, sum = 0;
/* 默认选择0号节点加入生成树,从1号节点开始初始化 */
for (i = 1; i < n; i++)
{
/* 最短距离初始化为其他节点到0号节点的距离 */
lowcost[i] = graph[0][i];
/* 标记所有节点的起点皆为默认的0号节点 */
mst[i] = 0;
}
/* 标记0号节点加入生成树 */
lowcost[0] = 0;
/* n个节点至少需要n-1条边构成最小生成树 */
for (i = 1; i < n; i++)
{
min = MAXCOST;
minid = 0;
/* 找满足条件的最小权值边的节点minid */
for (j =1; j <n; j++)
{
/* 边权值较小且不在生成树中 */
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
/* 输出生成树边的信息:起点,终点,权值 */
//cout<<"生成数边的起点、终点及权值分别为:"<< mst[minid]+1<<" "<<minid+1<<" "<<min<<endl;
/* 累加权值 */
sum += min;
/* 标记节点minid加入生成树 */
lowcost[minid] = 0;
/* 更新当前节点minid到其他节点的权值 */
for (j = 1; j < n; j++)
{
/* 发现更小的权值 */
if (graph[minid][j] < lowcost[j])
{
/* 更新权值信息 */
lowcost[j] = graph[minid][j];
/* 更新最小权值边的起点 */
mst[j] = minid;
}
}
}
/* 返回最小权值和 */
return sum;
}
int a[100][100];
int b[1000000][4];//存题目输入数据
int main()
{
int P,R,i,j,k;
while(~scanf("%d",&P)&&P!=0&&~scanf("%d",&R))
{
for(i=0;i<R;i++)
for(j=0;j<3;j++)
scanf("%d",&b[i][j]);
for(i=0;i<P;i++)
a[i][i]=0;//自身结点权值为0
for(i=0;i<P;i++)
for(j=0;j<P;j++)
if(i!=j)
{a[i][j]=max;a[j][i]=max;}//初始化为无穷大
for(k=0;k<R;k++)
{
i=b[k][0]-1;
j=b[k][1]-1;
if(a[i][j]==max)
{a[i][j]=b[k][2];a[j][i]=b[k][2];}//邻接矩阵
else
if(b[k][2]<a[i][j])
{a[i][j]=b[k][2];a[j][i]=b[k][2];}//筛选两节点之间最小成本。
}
printf("%d\n",Prim(a,P));
}
return 0;
}