您的位置:首页 > 理论基础 > 数据结构算法

数据结构实验之图论六:村村通公路

2019-08-06 22:52 387 查看

数据结构实验之图论六:村村通公路
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。
Input
连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。
Output
输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。
Sample Input

5 8
1 2 12
1 3 9
1 4 11
1 5 3
2 3 6
2 4 9
3 4 4
4 5 6

Sample Output

19

#include<bits/stdc++.h>

#define INF 0x3f3f3f3f

using namespace std;

int mmap[1111][1111];///邻接矩阵存储图
int vis[1111];       ///标记数组
int dis[1111];       ///
int prim(int n)
{
for(int i = 2; i <= n; i++)
dis[i] = mmap[1][i];  ///我们从0号节点开始生成树
vis[1] = 1;               ///生成树的根(起点)标记访问
int now;                  ///用来记录每一次循环找到的节点的编号
int sum = 0;              ///最小生成树的权值总和初始化为0
int mmin;
for(int i = 2; i <= n; i++)///要生成n-1条边,所以循环n-1次
{
mmin = INF;
for(int j = 2; j <= n; j++)///对dis数组进行遍历,找到值最小的
{
if(!vis[j] && dis[j] < mmin)
{
mmin = dis[j];
now = j;
}
}
sum += mmin;         ///加上找到的最小权值
vis[now] = 1;        ///标记找到的该节点被访问
if(mmin == INF)      ///如果在此跳出循环,表示有城市之间不能连通
return -1;///这个地方要注意,if()语句必须放在下面的循环前面,因为下面的是更新下一步的距离,为下一次循环准备
for(int j = 2; j <= n; j++)
{
if(!vis[j] && dis[j] > mmap[now][j])
dis[j] = mmap[now][j];///如果该点还没有被访问过,
}                             ///更新生成树到该点的距离;
}
return sum;
}
int main()
{
int n, m;
while(cin>>n>>m)
{
int a, b, c;
memset(vis, 0, sizeof(vis));///初始化节点均没有被访问
memset(dis, 0, sizeof(dis));
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(i == j)
mmap[i][j] = 0;
else
mmap[i][j] = INF;
}
}
while(m--)
{
scanf("%d%d%d", &a, &b, &c);
if(mmap[a][b] > c)///如果存在重边,取最小值
mmap[a][b] = mmap[b][a] = c;
}
cout<<prim(n)<<endl;///n指的是点的个数,不是起点数
}
return 0;
}

prim算法思路:
任一个顶点 u 作为生成树的根,
之 后往生成树上添加新的顶点 v在添加的顶点 w 和已经在生成树上的顶点v 之间必定存在一条边,
并且该边的权值在所有连通顶点 u和 v 之间的边中取值最小
之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。

上面是自己看着写的,下面是大神的,介绍prim算法,下面是它的代码
https://www.geek-share.com/detail/2619186140.html

#include<iostream>
#include<fstream>
using  namespace std;

#define MAX 100
#define MAXCOST 0x7fffffff

int graph[MAX][MAX];

int prim(int graph[][MAX], int n)
{
int lowcost[MAX];
int mst[MAX];
int i, j, min, minid, sum = 0;
for (i = 2; i <= n; i++)
{
lowcost[i] = graph[1][i];
mst[i] = 1;
}
mst[1] = 0;
for (i = 2; i <= n; i++)
{
min = MAXCOST;
minid = 0;
for (j = 2; j <= n; j++)
{
if (lowcost[j] < min && lowcost[j] != 0)
{
min = lowcost[j];
minid = j;
}
}
cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;
sum += min;
lowcost[minid] = 0;
for (j = 2; j <= n; j++)
{
if (graph[minid][j] < lowcost[j])
{
lowcost[j] = graph[minid][j];
mst[j] = minid;
}
}
}
return sum;
}

int main()
{
int i, j, k, m, n;
int x, y, cost;
ifstream in("input.txt");
in >> m >> n;//m=顶点的个数,n=边的个数
//初始化图G
for (i = 1; i <= m; i++)
{
for (j = 1; j <= m; j++)
{
graph[i][j] = MAXCOST;
}
}
//构建图G
for (k = 1; k <= n; k++)
{
in >> i >> j >> cost;
graph[i][j] = cost;
graph[j][i] = cost;
}
//求解最小生成树
cost = prim(graph, m);
//输出最小权值和
cout << "最小权值和=" << cost << endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: