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. linux 安装 phpstorm 并破解

    下载官方软件linux版phpstrom, 貌似很卡要FQ. 我下载我的百度网盘备用了.解压目录, mv 到/opt/ 下 cd进  bin目录下chmod  777 phpstorm.sh执行 ./ ...

  2. angular中处理多个异步请求的方法汇总

    在实际业务中经常需要等待几个请求完成后再进行下一步操作.但angularjs中$http不支持同步的请求. 解决方法一: $http多层嵌套 $http.get('url1').success(fun ...

  3. [luoguP2896] [USACO08FEB]一起吃饭Eating Together(DP)

    传送门 由于 Di 只有 3 种情况,那么就很简单了 f[i][j][0] 表示前 i 个,且第 i 个变成 j 的 递增序列最小修改次数 f[i][j][1] 表示前 i 个,且第 i 个变成 j ...

  4. C++ - 一个构造函数调用构造函数的问题

          今天做C++的实验,题目是写一个二维点的类,然后让一个三维点的类继承它然后扩展.题目是一般学面向对象语言的常用例子.       然后遇到一个这样的问题:之前用Java的时候写构造方法的时 ...

  5. [USACO5.3]校园网Network of Schools 缩点

    题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 B 在 A 学校的分发列表中, A 也不一定在 B 学校的列表中. 你要写 ...

  6. Ubuntu 16.04安装Chrome浏览器

    一.先有一个hosts能访问Google 参考:http://www.cnblogs.com/EasonJim/p/5999060.html 二.安装方法有两种,如下所示: 1.下载deb包(推荐) ...

  7. 22、Java并发性和多线程-Java中的读/写锁

    以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...

  8. v$log and v$logfiles

    v$log has one row for each group. v$logfile has one row for each file. There is a status column for ...

  9. 二维数组的查找,刷题成功——剑指Offer

    今天又做了一道题目,通过啦,欧耶! https://www.nowcoder.net/practice/abc3fe2ce8e146608e868a70efebf62e?tpId=13&tqI ...

  10. 条款50: 提高对C++的认识

    class Base { public: virtual void f(int x); }; class Derived: public Base { public: virtual void f(d ...