公路村村通

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

输入格式说明:

输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<=3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式说明:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出-1,表示需要建设更多公路。

样例输入与输出:

序号输入输出
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
2
3 1
2 3 2
-1
3
5 4
1 2 1
2 3 2
3 1 3
4 5 4
-1

分析:

这是一道求最小生成树的问题,给出城镇和城镇之间的费用作为权重,求出要连通所有城镇的最少费用,也就是求出这个图的最小生成树,当然不能连通时输出-1

我的思路就是先用邻接矩阵的方法存储图,然后就运用Prim算法求出这个图的最小生成树,最后输出最少费用dist


源码:

#include<iostream>
#include<stack>

#define MAXNUM 100000
#define NOEXIT -1

using namespace std;

int minDist(int dist[],bool flag[],int n)                  //求最小的dist
{
	int mindist = MAXNUM;
	int icount = NOEXIT;
	for(int i=1;i<n;i++)
	{
		if(dist[i] < mindist && flag[i] == false)
		{
			icount = i;
			mindist = dist[i];
		}
	}
	return icount;
 } 
 
int Prim(int *data[], int n, int m)
{
    // 集合: 用来存储收集到的结点
    stack<int> sta;
    sta.push(0);
    // dist: 记录长度
    int *dist = new int[n];
    for(int i=0;i<n;i++)
    {
    	dist[i] = MAXNUM;
	}
    dist[1] = 0;
    // collected: 标记是否被访问
    bool *collected = new bool[n];
    for(int i=0;i<n;i++)
    {
    	collected[i] = false;
	}
    // parent: 记录树的结构
    int *parent = new int[n];
    for(int i=0;i<n;i++)
	{
		parent[i] = NOEXIT;
	 } 
    // output: 最终结果
    int output = 0;
    while (1)
    {
        int V = minDist(dist, collected, n);
        if (V == NOEXIT)
            break;
        sta.push(V);
        output += dist[V];
        dist[V] = 0;
        collected[V] = true;
        for(int W=1; W<n; W++)
        {
            if(data[V][W] != MAXNUM         // 如果W是V的邻接点
               && collected[W] == false     // 如果W没有被访问
               && data[V][W] < dist[W])
            {
                dist[W] = data[V][W];
                parent[W] = V;
            }
        }
    }
    if(sta.size() != n)
        return NOEXIT;
    else
        return output;
}

int main()
{
	int n,m;
	cin>>n>>m;
	n++;
	//用邻接矩阵存储图
	int **data = new int*[n];
    for(int i=0; i<n; i++)
    {
        data[i] = new int[n];
    }
	//初始化 
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			data[i][j] = MAXNUM;
		}
	}
	for(int i=0;i<m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		data[a][b] = c;
		data[b][a] = c;
	}
	cout<<Prim(data,n,m) <<endl;
	return 0;
 } 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值