Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)
#1097 : 最小生成树一·Prim算法
描述
最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了!
但是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A、B、C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两条道路连通的)。
提示:不知道为什么Prim算法和Dijstra算法很像呢Σ(っ °Д °;)っ 。
提示:不知道为什么Prim算法和Dijstra算法很像呢Σ(っ °Д °;)っ 。
小Ho也是一路看着小Hi玩这个游戏过来的,于是便提出了自己的想法:“为什么一定要最少花费呢?随便造造能过关不就行了!”
小Hi怒道:“强迫症你知道什么意思么?”
于是小Ho闭嘴不敢言。
小Hi哼了一声,接着道:“也好,趁此机会,我可以教教你最小生成树是什么一回事——先说这个名字的由来,生成树这个名词是相对于一个确定的图G来的,也就是说你不能说一棵树T是生成树,只能说T是G的生成树,而生成树的意思就是,T的结点与G的结点是一样的,而且T的边集是G的边集的子集,这就是所谓的生成树。而最小生成树——意思就是G的所有生成树中边权和最小的一棵。”
“那么最小生成树可以有不止一棵吧?”小Ho问道。
小Hi点头答道:“是的,所以这个问题只需要输出最小生成树的边权和就可以了——这肯定是唯一的。”
小Ho挠了挠头,道:“那到底该怎么做呢?我一点头绪都没有——如果使用枚举的方式那时间复杂度是指数级别的,肯定做不出来!”
“且听我慢慢道来!”小Hi道:“首先我想证明一个结论:对于城市i(i≠1),如果i与城市1的距离不超过其他任何城市j(j≠1)与城市1的距离,那么(1, i)这一条边一定存在于某一棵最小生成树中。”
“你的意思是从城市1出发的最短的边一定属于某棵最小生成树?听上去有点道理,但是为什么啊?”小Ho问道。
小Hi点了点头:“证明是这样的:对于一棵最小生成树T——如果(1, i)在其中,那么该结论就已经得到了证明,所以我们考虑的是(1, i)不在其中的情况。而1和i之间肯定会通过某条路径连通(因为是树不是森林),不妨假设为1-p1-p2-...-pk-i。”
“嗯嗯,然后呢?”
“那么,如果我将(1, p1)这条边删去,添加上(1, i)这条边,那么这还是一棵生成树么?”小Hi问道。
“点没有发生变化,边集仍然是图G的子集,那么只需要看还是不是一个棵树了——所有点之间仍然连通,而且没有环(添加边(1, i)后仅有一个环1-p1-p2-...-pk-i-1,但是(1, p1)却被删去了)!所以这还是一棵树,也就是说……这样改动之后仍然是一棵生成树。”小Ho想了想,说道。
“如果我们称改动后的生成树为T'的话,不难发现,由于(1, p1)的费用大于等于(1, i)的费用,我们可以知道T'的边权和小于等于T,又因为T本身已经是最小生成树了,不难发现T'也会是最小生成树……”小Ho恍然大呼:“也就是说结论得到了证明:(1, i)这一条边一定存在于某一棵最小生成树中。”
“对的!所以万里长征第一步已经走完了,接下来只需要按照第一步走下去就行了!”小Hi道。
“什么意思……接下来的情况要复杂很多吧?”小Ho困惑了。
小Hi叹了口气道:“笨……你这么想,如果我确定了(1, i)这条边一定存在于某一棵最小生成树中,那么我仿照Dijstra算法的思想,将1和i合并为一个点,那么问题是不是就变成了求剩下的N-2个点和这个点的最小生成树?问题没有变化,但是规模却缩小了,那么就只需要一次一次的进行这样的步骤,这个问题不是就能够完美的解决了么?”
小Ho边思索边道:“也就是说……对于一个N个点的最小生成树问题,我求出与1号点最近的点i,将这两个点合并,剩下N-1个点,然后求与新的1号点最近的点i',将这两个点合并,剩下了N-2个点……然后依次类推,直到最后剩下一个点的时候,再将之前所有合并的边的费用加起来——就是答案了!”
“孺子可教也,赶紧去把程序写了!我一会要用呢!”
输入
每个测试点(输入文件)有且仅有一组测试数据。
在一组测试数据中:
第1行为1个整数N,表示小Hi拥有的城市数量。
接下来的N行,为一个N*N的矩阵A,描述任意两座城市之间建造道路所需要的费用,其中第i行第j个数为Aij,表示第i座城市和第j座城市之间建造道路所需要的费用。
对于100%的数据,满足N<=10^3,对于任意i,满足Aii=0,对于任意i, j满足Aij=Aji, 0<Aij<10^4.
输出
对于每组测试数据,输出1个整数Ans,表示为了使任意两座城市都可以通过所建造的道路互相到达至少需要的建造费用。
- 样例输入
-
5
0 1005 6963 392 1182
1005 0 1599 4213 1451
6963 1599 0 9780 2789
392 4213 9780 0 5236
1182 1451 2789 5236 0 - 样例输出
-
4178 vector可变长数组可以模拟邻接表,但是这种存储结构用于处理多组数据时,一定要把vector数组全部清空
否则,必然WA! 代码:#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <iostream>
#define INF 2100000000
using namespace std;
struct node
{
int dd;
int w;
}t; vector<node>q[1001];
int dis[1001];
bool vis[1001];
void Vector_prim(int n)
{
int i, j;
vector<node>::iterator it;
memset(vis, false, sizeof(vis));
memset(dis, INF, sizeof(dis));
for(it=q[1].begin(); it!=q[1].end(); it++ )
{
dis[it->dd]=it->w;
}
vis[1]=true;
int pos;
int sum=0; for(i=1; i<n; i++ )
{
int mm=INF;
for(j=1; j<=n; j++)
{
if(!vis[j] && dis[j]<mm )
{
mm=dis[j];
pos=j;
}
}
sum+=mm;
vis[pos]=true;
for(it=q[pos].begin(); it!=q[pos].end(); it++ )
{
if( !vis[it->dd] && it->w <dis[it->dd] )
{
dis[it->dd]=it->w;
}
}
}
printf("%d\n", sum );
} int main()
{
int n;
int i, j;
int w;
scanf("%d", &n);
for(i=0; i<=n; i++)
{
q[i].clear();
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
scanf("%d", &w);
if(i!=j)
{
t.dd=j;
t.w=w;
q[i].push_back(t);
}
}
}
Vector_prim(n);
return 0;
}
Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)的更多相关文章
- 做了一道跑大数据的最短路挂了,基于vector的二维模拟邻接表实现Dijkstra算法(*【模板】)
代码: #include <stdio.h> #include <string.h> #include <string> #include <vector&g ...
- 【PS算法理论探讨二】 Photoshop中图层样式之 投影样式 算法原理初探讨。
接下来几篇文章我们将稍微简单的探索下PS中多种图层混合模式的算法内部原理,因为毕竟没有这方面的官方资料,所以很多方面也只是本人自己的探索和实践,有可能和实际的情况有着较大的差异. 在PS的实践中,图层 ...
- 基于visual Studio2013解决算法导论之053图的邻接表表示
题目 图的邻接表表示 解决代码及点评 // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <sta ...
- AOJ GRL_1_A: Single Source Shortest Path (Dijktra算法求单源最短路径,邻接表)
题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A Single Source Shortest Path In ...
- STP生成树算法
生成树算法第一:决定谁是“根网桥”对比各个网桥ID,先对比ID中的优先级,优先级相同的时候对比网桥MAC地址,对比依据是谁的值最小,谁是“根网桥” 第二:决定哪些是“根端口”窍门——每个非根网桥上都有 ...
- STP概述简介及生成树算法
目录: STP概述 STP简介 生成树算法 选择根网桥 选择根端口 选择指定端口 BPDU(桥协议数据单元) STP利用BPDU选择根网桥 STP的收敛 VLAN与STP关系 MSTP多生成树协议华为 ...
- Java数据结构与算法解析(十二)——散列表
散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...
- HDU 1535 Invitation Cards(逆向思维+邻接表+优先队列的Dijkstra算法)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1535 Problem Description In the age of television, n ...
- 递归分治算法之二维数组二分查找(Java版本)
[java] /** * 递归分治算法学习之二维二分查找 * @author Sking 问题描述: 存在一个二维数组T[m][n],每一行元素从左到右递增, 每一列元素从上到下递增,现在需要查找元素 ...
随机推荐
- BZOJ 1006 [HNOI2008]神奇的国度==最大势算法
神奇的国度 K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在. ...
- 标准C程序设计七---17
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- 标准C程序设计七---16
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- linux的crontab定时任务命令
linux的crontab定时任务命令 cron是一个linux下的定时执行工具. 启动.停止.重启.重新载入配置/sbin/service crond start|stop|restart|relo ...
- Day 12 shell语法及程序若干
1. 现归纳一下shell中的运算符: +:对两个变量做加法. -:对两个变量做减法. *:对两个变量做乘法. /:对两个变量做除法. **:对两个变量做幂运算. ...
- 升级python2至python3解决依赖关系
1.最小化安装centos7,在升级python3的时候会出现很多包未安装,为解决依赖关系: yum -y install gcc gcc-c++ zlib zlib-devel libffi-dev ...
- Spring实战Day6
3.4 bean的作用域 Spring中bean的作用域 单例(Singleton):在整个应用中,只创建bean的一个实例. 原型(Prototype):每次注入或者通过Spring应用上下文获取的 ...
- JStorm学习
一.简介 JStorm是一个分布式实时计算引擎.JStorm是一个类似于Hadoop MapReduce的系统,用户按照指定的接口实现一个任务,然后将这个任务交给JStorm系统,JStorm将这个任 ...
- c++引用和const 用法 数组 指针
非const引用,只能用object为其赋值: <c++primer>P52 而const引用则可以用临时变量为其赋值: 如: const int &r = 32://可以 int ...
- 从头认识java-15.5 使用LinkedHashSet须要注意的地方
再接着上一个章节.我们来聊一下使用LinkedHashSet须要注意的地方. LinkedHashSet特点: (1)元素是有顺序的 (2)元素是不反复的 (3)底层数据结构是依照链表的结构存储的 ( ...