#1097 : 最小生成树一·Prim算法

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了!

但是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A、B、C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两条道路连通的)。

提示:不知道为什么Prim算法和Dijstra算法很像呢Σ(っ °Д °;)っ 。

×Close

提示:不知道为什么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个点……然后依次类推,直到最后剩下一个点的时候,再将之前所有合并的边的费用加起来——就是答案了!”

“孺子可教也,赶紧去把程序写了!我一会要用呢!”

Close      

输入

每个测试点(输入文件)有且仅有一组测试数据。

在一组测试数据中:

第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()生成树算法, *【模板】)的更多相关文章

  1. 做了一道跑大数据的最短路挂了,基于vector的二维模拟邻接表实现Dijkstra算法(*【模板】)

    代码: #include <stdio.h> #include <string.h> #include <string> #include <vector&g ...

  2. 【PS算法理论探讨二】 Photoshop中图层样式之 投影样式 算法原理初探讨。

    接下来几篇文章我们将稍微简单的探索下PS中多种图层混合模式的算法内部原理,因为毕竟没有这方面的官方资料,所以很多方面也只是本人自己的探索和实践,有可能和实际的情况有着较大的差异. 在PS的实践中,图层 ...

  3. 基于visual Studio2013解决算法导论之053图的邻接表表示

     题目 图的邻接表表示 解决代码及点评 // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <sta ...

  4. 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 ...

  5. STP生成树算法

    生成树算法第一:决定谁是“根网桥”对比各个网桥ID,先对比ID中的优先级,优先级相同的时候对比网桥MAC地址,对比依据是谁的值最小,谁是“根网桥” 第二:决定哪些是“根端口”窍门——每个非根网桥上都有 ...

  6. STP概述简介及生成树算法

    目录: STP概述 STP简介 生成树算法 选择根网桥 选择根端口 选择指定端口 BPDU(桥协议数据单元) STP利用BPDU选择根网桥 STP的收敛 VLAN与STP关系 MSTP多生成树协议华为 ...

  7. Java数据结构与算法解析(十二)——散列表

    散列表概述 散列表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 散列表的思路很简单,如果所有的键都是整数,那么就可以使用一个简单 ...

  8. HDU 1535 Invitation Cards(逆向思维+邻接表+优先队列的Dijkstra算法)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1535 Problem Description In the age of television, n ...

  9. 递归分治算法之二维数组二分查找(Java版本)

    [java] /** * 递归分治算法学习之二维二分查找 * @author Sking 问题描述: 存在一个二维数组T[m][n],每一行元素从左到右递增, 每一列元素从上到下递增,现在需要查找元素 ...

随机推荐

  1. 使用HttpClient实现对第三方服务器的请求并接受返回数据

    /* * 创建日期 2017-4-7 * * TODO 要更改此生成的文件的模板,请转至 * 窗口 - 首选项 - Java - 代码样式 - 代码模板 */ package com.enfo.int ...

  2. ElasticSearch API 之 DELETE

    删除API,可以根据特定的ID删除文档. $ curl -XDELETE 'http://localhost:9200/website/blog/AVbkih8AltSLRRB7XAun' 会返回下面 ...

  3. Laravel 静态资源管理

    <link rel="stylesheet" href="{{ asset('bootstrap/css/bootstrap.min.css') }}" ...

  4. [bzoj3622]已经没有什么好害怕的了_动态规划_容斥原理

    bzoj-3622 已经没有什么好害怕的了 题目大意: 数据范围:$1\le n \le 2000$ , $0\le k\le n$. 想法: 首先,不难求出药片比糖果小的组数. 紧接着,我开始的想法 ...

  5. scp操作实例

    scp 可用于文件的上传与下载,默认端口号是22,通常我们为了安全起见会将默认端口号修改了,而不去直接使用默认的22端口,以下我们以8888端口为例 目标机器 A :192.168.10.30 目标机 ...

  6. 线性表的顺序存储和链式存储的实现(C)

    //线性表的顺序存储 #include <stdio.h>typedef int DataType;#define MaxSize 15//定义顺序表typedef struct { Da ...

  7. 递归获取JSON内容的key-value值

    方法主体: 使用时,请在类中先声明一个Map,參数形式例如以下: JSONObject jobj = new JSONObject(JSONContent); 首次请传递jobj.

  8. Solidedge如何新建参考平面 参考面

    1 建立平行平面 点击平行平面 点击参考平面,输入相对距离   2 建立成角平面 先选择基准面,再选则旋转轴(第二次点击一个平面,该平面与基准面相交形成的直线即为旋转轴)   输入角度即可完成(鼠标左 ...

  9. MongoDB:分片(简介 & 自动分片 & 片键)

    分片(增加服务器,水平扩展)是MongoDB的扩展方式,通过分片能过增加更多的机器来应对不断增加的负载和数据,还不影响应用. [简介] 分片(sharding)是指将数据拆分,将其分散存在不同的机器上 ...

  10. @Transactional 无效的解决方案

    1 .在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上 . 2 . @Transactio ...