Problem Description:

大二上学期刚过完,平时成绩不错的小V参加了一个小型编程比赛,遇到一道题,虽然是书上的却不会做。于是找了在机房的他帮忙。
他:什么题目这么厉害,书上有却不会?
小V:就是给若干个城市编号,也告诉了我连接这些城市的公路的距离,也有一些城市间是没有直接的路的。求从一个城市到另外一个城市的最短距离。
他:这不很简单的单向最短路径么?照书敲都行啦。
小V:不是什么比赛都能带书。
他:那你自己敲出来还不行么?
小V:不会敲..完全下不了手,我只会考试那种画图的,写代码的话连思路都没有。
他:好吧- -!思路是这样的:
s为起点,w[u,v]为点u和v之间的边的长度(无边则长度设为一个很大的数,只要比w[]的最大值大就行),把s点到其他点的距离保存在一个数组里,假设是dis[]。
1.初始化:起点到起点的距离dis[s]设为0,s点到其他点(v)的距离设w[s,v],同时把所有的点都标记为未访问过,s点标记访问过。
2.循环n-1次:
①在没有访问过的点中取dis[]距离最小且未访问的点u,并标记为已访问。
②对于每个与u相邻的点v,执行Relax(u,v),也就是说,如果满足u点在最短路径上的距离+u到v点距离小于原本v点到最短路径上的距离就把v点到最短路径的距离更新成更短的距离。
3.结束。此时对于任意的u,dis[u]就是s到u的距离。
小V:标记?
他:开个数组表示就行了。
小V:那我试敲下。
他:等会,顺便先判断下这些城市能不能从任意一个城市i到另外一个城市j吧。
小V:生成树?
他:这么聪明?不过判断连通不一定要生成树,你还可以用搜索、并查集,搜索就看能不能一次就搜遍,集合就看是不是它们在同一连通分量,不是就把它们合并在一个集合里,最终判断是不是全部点同属一个集合就行。
小V:那个叫什么并查集的怎么听起来跟克鲁斯卡尔算法那么像。
他:kruskal是可以用并查集优化的。不过既然你这么说了,那就干脆也求个最小生成树的值吧,即用公路长度和最小的n-1个公路将n个城市连在一起,求这n-1条路的公路长度。
小V:那代码上跟最短路那个算法有什么区别?
他:改下Relax()的条件,每加入一个点u,看其他跟该点有边的点v,v到树上的距离是不是小于u到树上源点的距离,是就更新,再把生成树上那些点的权值加起来就是答案。
大概半小时后,小V敲得差不多了。
他:看你都敲这么多了,也告诉你这么多了,不如加个难度,改求最大生成树,这样,我给你4个例子,你对照下答案。
经过比对,答案还是不对。这时他喵了一眼就看出是初始化问题,但他没有告诉她。因为他知道这是她必须跨过的坎,有多少学生能把各种算法的原理讲得很流畅,却写不出代码。
而对于她,他希望她能解决的不只是这个问题,因为这样才能实现他的心愿:一!起!刷!题! Hints:不要轻易放弃,水题虽多,AC不易。

Input:

多组数据,每组数据第一行是两个数N,M(1<=N<=100,0<=M<=1000),N表示城市个数,城市从1开始编号,M表示公路数目,编号为1的城市为起点,编号为N的为终点,接下来有M行,每行两个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示有一条长度为C的公路连接AB两城市。数据保证1号城市不是孤立的。

Output:

如果从1号城市出发,不能到其他所有城市,则输出-1,否则按样例格式输出最大生成树的值和从1号城市到N号城市的最短距离。

Sample Input:

3 3
1 2 45
1 3 20
3 1 10
3 1
1 2 5
2 2
2 1 250
1 2 520
4 7
1 4 88
2 4 1
4 2 50
3 1 6
4 1 1000
4 3 30
2 3 100

Sample Output:

spanning tree:65 shortest distance:10
-1
spanning tree:520 shortest distance:250
spanning tree:1150 shortest distance:36
解题思路:最大生成树即将prim算法中每次找最小权值改为找最大权值,每加入一个点更新一下用最大权值代替原来的最小值即可。这题还要考虑重边的情况,简单处理,简单水过。
AC代码:
 #include<bits/stdc++.h>
using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
int n,m,a,b,c,maxcost[maxn],dist[maxn],G[maxn][maxn],cost[maxn][maxn];bool vis[maxn],used[maxn];
int prim(){//最大生成树
for(int i=;i<=n;++i)maxcost[i]=G[][i];
maxcost[]=;used[]=true;
int res=;
for(int i=;i<n;++i){
int k=-;
for(int j=;j<=n;++j)
if(!used[j]&&(k==-||maxcost[k]<maxcost[j]))k=j;//每次找最大边权
if(k==-)break;
used[k]=true;res+=maxcost[k];
for(int j=;j<=n;++j)
if(!used[j])maxcost[j]=max(maxcost[j],G[k][j]);//更新周围点到已经归纳点的集合的最小权值
}
return res;
}
int dijkstra(){//最短路径
for(int i=;i<=n;++i)dist[i]=cost[][i];
dist[]=;vis[]=true;
for(int i=;i<n;++i){
int k=-;
for(int j=;j<=n;++j)
if(!vis[j]&&(k==-||dist[k]>dist[j]))k=j;
if(k==-)break;
vis[k]=true;
for(int j=;j<=n;++j)
if(!vis[j])dist[j]=min(dist[j],dist[k]+cost[k][j]);
}
return dist[n];
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(vis,false,sizeof(vis));//全部初始化为未访问状态即false
memset(used,false,sizeof(used));
for(int i=;i<=n;++i){
for(int j=;j<=n;++j){
G[i][j]=(i==j?:-INF);//求最大生成树:初始化为最小值-INF
cost[i][j]=(i==j?:INF);//求最短路径:初始化为最大值INF
}
}
for(int i=;i<=m;++i){
scanf("%d%d%d",&a,&b,&c);
G[a][b]=G[b][a]=max(G[a][b],c);//去重,代替最小权值
cost[a][b]=cost[b][a]=min(cost[a][b],c);//去重,代替最大权值
}
int ok=prim();
if(ok<=)cout<<-<<endl;//如果不大于0,说明不能从1到达n,直接输出-1
else cout<<"spanning tree:"<<ok<<" shortest distance:"<<dijkstra()<<endl;
}
return ;
}
 

ACM_他和她(最大生成树+最短路径)的更多相关文章

  1. ACM主要算法

    ACM主要算法ACM主要算法介绍 初期篇 一.基本算法(1)枚举(poj1753, poj2965)(2)贪心(poj1328, poj2109, poj2586)(3)递归和分治法(4)递推(5)构 ...

  2. ACM常用算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  3. ACM需要掌握算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  4. ACM用到的算法。先做个笔记,记一下

    ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 ...

  5. ACM算法目录

    数据结构 栈,队列,链表 •哈希表,哈希数组 •堆,优先队列 双端队列 可并堆 左偏堆 •二叉查找树 Treap 伸展树 •并查集 集合计数问题 二分图的识别 •平衡二叉树 •二叉排序树 •线段树 一 ...

  6. ACM技能表

    看看就好了(滑稽) 数据结构 栈 栈 单调栈 队列 一般队列 优先队列/单调队列 循环队列 双端队列 链表 一般链表 循环链表 双向链表 块状链表 十字链表 邻接表/邻接矩阵 邻接表 邻接多重表 Ha ...

  7. 图论相关知识(DFS、BFS、拓扑排序、最小代价生成树、最短路径)

    图的存储 假设是n点m边的图: 邻接矩阵:很简单,但是遍历图的时间复杂度和空间复杂度都为n^2,不适合数据量大的情况 邻接表:略微复杂一丢丢,空间复杂度n+m,遍历图的时间复杂度为m,适用情况更广 前 ...

  8. 信息奥赛一本通1486: CH 6202 黑暗城堡 最短路径生成树计数

    1486:黑暗城堡 [题目描述] 知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度. 城堡是树形的并且满足下面的条件: 设 Di为如果所有的通道都被修建,第 i 号房间与第 1 ...

  9. acwing349 黑暗城堡 (最短路径生成树)

    求出最短树,用乘法原理统计答案就行了(模拟prim过程). 不知道说什么了,直接上代码: 1 #include<cstring> 2 #include<iostream> 3 ...

随机推荐

  1. Python网络编程—socket(二)

    http://www.cnblogs.com/phennry/p/5645369.html 接着上篇博客我们继续介绍socket网络编程,今天主要介绍的内容:IO多路复用.多线程.补充知识点. 一.I ...

  2. NOIP2015 提高组合集

    NOIP 2015 提高组 合集 D1 T1 神奇的幻方 题目让你干啥你就干啥,让你咋走你就咋走就完事儿了 #include <iostream> #include <cstdio& ...

  3. 为什么说Ubuntu的运行级别为2

    继上一篇文章http://www.cnblogs.com/EasonJim/p/7163069.html深入研究了Linux的运行级别之后,发现网上大部分都说Ubuntu的运行级别默认为2,那么下面就 ...

  4. 桦仔------分享一下我研究SQLSERVER以来收集的笔记

    http://www.cnblogs.com/lyhabc/p/3219117.html

  5. zabbix全方位监控MySQL +cacti监控mysql

    http://www.linuxidc.com/Linux/2015-02/112690.htm http://john88wang.blog.51cto.com/2165294/1596272?ut ...

  6. android学习笔记(9)android程序调试学习

    相应若水老师的第十四课 一,Log日志输出 Log.v(tag,message);        //verbose模式,打印最具体的日志  Log.d(tag,message);        // ...

  7. $.getJSON() 未能执行回调函数的缘由

    $.getJSON() 方法使用 AJAX 的 HTTP GET 请求获取 JSON 数据. 语法 1 $.getJSON(url,data,success(data,status,xhr)) url ...

  8. C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断

    C#保留2位小数几种场景总结   场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...

  9. Java 实现抽象工厂模式

    抽象工厂模式 里面有几个概念:抽象工厂.实体工厂.抽象产品.实体产品 抽象工厂:定义创建产品的抽象方法 实体工厂:详细的创建哪种产品 抽象产品:一个接口或基类 实体产品:实现详细功能,或派生 类图 ...

  10. Nodejs创建HTTPS服务器

    Nodejs创建HTTPS服务器 从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Jav ...