ACM_他和她(最大生成树+最短路径)
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_他和她(最大生成树+最短路径)的更多相关文章
- ACM主要算法
ACM主要算法ACM主要算法介绍 初期篇 一.基本算法(1)枚举(poj1753, poj2965)(2)贪心(poj1328, poj2109, poj2586)(3)递归和分治法(4)递推(5)构 ...
- ACM常用算法
数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...
- ACM需要掌握算法
数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...
- ACM用到的算法。先做个笔记,记一下
ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 ...
- ACM算法目录
数据结构 栈,队列,链表 •哈希表,哈希数组 •堆,优先队列 双端队列 可并堆 左偏堆 •二叉查找树 Treap 伸展树 •并查集 集合计数问题 二分图的识别 •平衡二叉树 •二叉排序树 •线段树 一 ...
- ACM技能表
看看就好了(滑稽) 数据结构 栈 栈 单调栈 队列 一般队列 优先队列/单调队列 循环队列 双端队列 链表 一般链表 循环链表 双向链表 块状链表 十字链表 邻接表/邻接矩阵 邻接表 邻接多重表 Ha ...
- 图论相关知识(DFS、BFS、拓扑排序、最小代价生成树、最短路径)
图的存储 假设是n点m边的图: 邻接矩阵:很简单,但是遍历图的时间复杂度和空间复杂度都为n^2,不适合数据量大的情况 邻接表:略微复杂一丢丢,空间复杂度n+m,遍历图的时间复杂度为m,适用情况更广 前 ...
- 信息奥赛一本通1486: CH 6202 黑暗城堡 最短路径生成树计数
1486:黑暗城堡 [题目描述] 知道黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度. 城堡是树形的并且满足下面的条件: 设 Di为如果所有的通道都被修建,第 i 号房间与第 1 ...
- acwing349 黑暗城堡 (最短路径生成树)
求出最短树,用乘法原理统计答案就行了(模拟prim过程). 不知道说什么了,直接上代码: 1 #include<cstring> 2 #include<iostream> 3 ...
随机推荐
- Python网络编程—socket(二)
http://www.cnblogs.com/phennry/p/5645369.html 接着上篇博客我们继续介绍socket网络编程,今天主要介绍的内容:IO多路复用.多线程.补充知识点. 一.I ...
- NOIP2015 提高组合集
NOIP 2015 提高组 合集 D1 T1 神奇的幻方 题目让你干啥你就干啥,让你咋走你就咋走就完事儿了 #include <iostream> #include <cstdio& ...
- 为什么说Ubuntu的运行级别为2
继上一篇文章http://www.cnblogs.com/EasonJim/p/7163069.html深入研究了Linux的运行级别之后,发现网上大部分都说Ubuntu的运行级别默认为2,那么下面就 ...
- 桦仔------分享一下我研究SQLSERVER以来收集的笔记
http://www.cnblogs.com/lyhabc/p/3219117.html
- zabbix全方位监控MySQL +cacti监控mysql
http://www.linuxidc.com/Linux/2015-02/112690.htm http://john88wang.blog.51cto.com/2165294/1596272?ut ...
- android学习笔记(9)android程序调试学习
相应若水老师的第十四课 一,Log日志输出 Log.v(tag,message); //verbose模式,打印最具体的日志 Log.d(tag,message); // ...
- $.getJSON() 未能执行回调函数的缘由
$.getJSON() 方法使用 AJAX 的 HTTP GET 请求获取 JSON 数据. 语法 1 $.getJSON(url,data,success(data,status,xhr)) url ...
- C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断
C#保留2位小数几种场景总结 场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...
- Java 实现抽象工厂模式
抽象工厂模式 里面有几个概念:抽象工厂.实体工厂.抽象产品.实体产品 抽象工厂:定义创建产品的抽象方法 实体工厂:详细的创建哪种产品 抽象产品:一个接口或基类 实体产品:实现详细功能,或派生 类图 ...
- Nodejs创建HTTPS服务器
Nodejs创建HTTPS服务器 从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Jav ...