poj 2421 Constructing Roads(最小生成树prim)
2015-07-27 17:13
411 查看
题目地址
题目大意:给出一个图有n个点,以矩阵的形式给出点与点之间的权值,告诉其中m条边(边的端点)已经存在,求将整个图联通还需的最小权值和
解题思路:首先判断为最小生成树,题目以矩阵的形式给出数据,用prim算法,因为已经给出部分边已联通,处理一下,直接模板
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <list>
#include <set>
using namespace std;
const int maxn = 100+10;
const int INF = 0xfffffff;
int mp[maxn][maxn],low[maxn],visited[maxn];//mp数组邻接矩阵存储图,low数组记录集合外的每个点与集合内的最小权值,visited数组标记某点是否已访问
int n;//n个点
int prim()
{
int pos,Min;//pos为刚加入的点,Min为当前情况下要加入边的权值(当前最小)
int result = 0;//存储最小权值和
memset(visited,0,sizeof(visited));
visited[1] = 1;//从某点开始,分别标记
pos = 1;//从某点开始,记录该点
for(int i = 1; i <= n; i++)
if(i != pos) low[i] = mp[pos][i];//初始化low数组
for(int i = 1; i < n; i++)//再运行n-1次(起点已经进入集合)使n个点全部进入集合
{
Min = INF;//找出最小权值并记录位置
for(int j = 1; j <= n; j++)
if(!visited[j] && Min > low[j])//对于每个点如果没有进入集合并且该点与集合的距离比当前的最小权值小则更新
{
Min = low[j];
pos = j;
}
result += Min;//最小权值累加
visited[pos] = 1;//标记该点,进入集合
for(int j = 1; j <= n; j++)//更新权值(刚进入的点对权值的影响)
if(!visited[j] && low[j] > mp[pos][j])
low[j] = mp[pos][j];
}
return result;
}
int main()
{
int m,a,b;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
mp[i][j] = INF;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%d",&mp[i][j]);
}
}
scanf("%d",&m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&a,&b);
mp[a][b] = mp[b][a] = 0;
}
int ans = prim();
printf("%d\n",ans);
return 0;
}
题目大意:给出一个图有n个点,以矩阵的形式给出点与点之间的权值,告诉其中m条边(边的端点)已经存在,求将整个图联通还需的最小权值和
解题思路:首先判断为最小生成树,题目以矩阵的形式给出数据,用prim算法,因为已经给出部分边已联通,处理一下,直接模板
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <list>
#include <set>
using namespace std;
const int maxn = 100+10;
const int INF = 0xfffffff;
int mp[maxn][maxn],low[maxn],visited[maxn];//mp数组邻接矩阵存储图,low数组记录集合外的每个点与集合内的最小权值,visited数组标记某点是否已访问
int n;//n个点
int prim()
{
int pos,Min;//pos为刚加入的点,Min为当前情况下要加入边的权值(当前最小)
int result = 0;//存储最小权值和
memset(visited,0,sizeof(visited));
visited[1] = 1;//从某点开始,分别标记
pos = 1;//从某点开始,记录该点
for(int i = 1; i <= n; i++)
if(i != pos) low[i] = mp[pos][i];//初始化low数组
for(int i = 1; i < n; i++)//再运行n-1次(起点已经进入集合)使n个点全部进入集合
{
Min = INF;//找出最小权值并记录位置
for(int j = 1; j <= n; j++)
if(!visited[j] && Min > low[j])//对于每个点如果没有进入集合并且该点与集合的距离比当前的最小权值小则更新
{
Min = low[j];
pos = j;
}
result += Min;//最小权值累加
visited[pos] = 1;//标记该点,进入集合
for(int j = 1; j <= n; j++)//更新权值(刚进入的点对权值的影响)
if(!visited[j] && low[j] > mp[pos][j])
low[j] = mp[pos][j];
}
return result;
}
int main()
{
int m,a,b;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
mp[i][j] = INF;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
scanf("%d",&mp[i][j]);
}
}
scanf("%d",&m);
for(int i = 1; i <= m; i++)
{
scanf("%d%d",&a,&b);
mp[a][b] = mp[b][a] = 0;
}
int ans = prim();
printf("%d\n",ans);
return 0;
}
相关文章推荐
- Notes消除冲突文档
- Android侧滑控件之DrawerLayout的使用
- 【九】鸟哥私房菜
- 【Linux】 CPU亲和性(affinity)及与亲和性有关的两个函数 sched_setaffinity()和 sched_getaffinity()
- 取模运算的性质
- STL的学习
- mvn -version时报错:java.lang.UnsupportedClassVersionError
- C#高级编程五十八天----并行集合
- 为mysql数据库建立索引
- 表关系
- iOS 在UILabel显示不同的字体和颜色
- CDN和反向代理
- Palindrome Linked List
- UNITY3D学习笔记6
- 当GridView嵌入ListView后,获取不到Listview的Item 点击事件
- Ubuntu15.04 + Matlab2014a + MatConvNet install and compile
- zigbee编译调试时可能出现的问题
- Ubuntu15.04 + Matlab2014a + MatConvNet install and compile
- HDOJ题目4705 Y(简单树形DP+数学)
- 面向 C++ 的测试驱动开发