随笔分类 - 最短路径
1
摘要:题意:给定一个n+1个点的有向图和起点,求经过其余n个点然后回到起点的最短路径。。(n<=10)分析:看到这么小的数据,就知道不是普通的最短路了,首先,n 这么小,应该联想到的应该是状态压缩吧,每一个位表示经过了哪一个点。。。dp[i][j] 表示到达点i 状态为j 时的最短路径长度,一开始忽略了一点,就是更新过的点,完全有可能再更新的,所以不能单纯记录是否更新过该状态,所以就想到了用spfa,将更新过的点入队,,继续拓展……View Code #include<iostream>#include<algorithm>#include<queue>us
阅读全文
摘要:题意: 给定一个有向图,有路径(边)权值和节点的权值,求一个字典序最小的最短路径(中间节点权值+路径权值)分析:此题目需要对floyd算法有比较深的了解,首先floyd是一个不断拓展路径的过程,同时也是不断增加中间节点的过程,所以累加中间节点权值的部分很好处理。理解了floyd 算法的过程之后,记录路径也非难事,关键是题目要求的是字典序最小的最短路径。记录路径有俩种方式:1)path[i][j]记录起点为i ,终点为j 的路径上j 的直接前驱View Code void init(int n){ for(int i=1;i<=n;i++) for(int j=1;j<=n;...
阅读全文
摘要:题意:求出1到N 的无向图的无重复边的最短路径数(即所有的最短路径没有公共边)分析:先求出最短路,再找出所有属于最短路的边(满足dist[u]+g[u][v]==dist[v]),把有向边(u,v)加入到新图中,容量为1,(即每条边只能用一次),最后求一次源点为1,汇点为t的最大流即可View Code #include<iostream>#include<algorithm>#include<string>#include<vector>#include<stack>using namespace std;const int N =
阅读全文
摘要:hdu1688题意:找出从S到F两个点之间的最短路和比最短路长1的次短路的条数之和。分析:最短路很好求,关键是次短路,郁闷呀不过,如果对最短路的更新距离的过程有更深的认识的话,就好办很多了。用一个二维数组记录每一个节点距离起始点的最短距离和次短距离,再开一个二维数组记录路径数更新状态时:1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数2)新值等于最短路径长:更新最短路径计数3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数4)新值等于次短路径长:更新次短路径计数View Code #include<iostream>#include<algorithm
阅读全文
摘要:先求一遍最短路,再根据求出来的每一个点到达终点的最短距离,dfs计数View Code #include<iostream>#include<algorithm>using namespace std;const int N =1001;int g[N][N],n,m,dist[N];int ans,dp[N];bool vis[N];void init(){ for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) g[i][j]=INT_MAX;}void Dijkstra(int s){ memset(vis,...
阅读全文
摘要:Problem Description给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。Input输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。(1<n<=1000, 0<m<100000, s != t)Output输出 一行有两个数, 最短距离及其花费。分析:每条路径增加 了一个权值,但还是一道最短路的问题,只需要在更新距离的时候判断一下
阅读全文
摘要:大致题意是说:有n个电站,每个电站都有一定的电量,电站之间有一定距离,我们要从0点出发去占领一些电站,使得占领的电站电量之和超过总电量的一半,求达到条件所要走的最短距离。如果可能的话,输出距离,否则输出不可能。我们知道电站都是连通的,只要0点与任何一个电站连通,我们就可以占领所有电站,如果0点不与任何一个电站相连,就是不可能实现,也就是说0点到任何一个电站的距离都是无穷。 我们从0点开始派出一些坦克去占领一些电站,坦克到每个电站都有一定距离,而占领每个电站之后可以得到一定电量,距离就相当于体积,电量就相当于价值,这不是就01背包吗?01背包通常的问法是给定体积,求获得最大的价值,这里的问法是给
阅读全文
摘要:题意:求到达任意俩点之间的最小消费,也可以说求任意俩点的最短路径啦分析:很直接的就是用floyd算法,很好写的一个算法,最坑爹的是距离要用__int64保存当然,对每一次询问都用单源最短路算法的SPFA 也行,不过慢了一点floyd#include<iostream>#include<algorithm>#include<math.h>#define MAXN 100+10using namespace std;int L[4],C[4],n;int X[MAXN];__int64 g[MAXN][MAXN];int get_dis(int i,int j)
阅读全文
摘要:中文题,题意就不说了不过想不到并查集这样用对于题目中的路,按速度进行排序,这样,如果从第 i 条路到第 j 条路之间的所有路能够让 i 和 j 连通,那么,这就存在一条路,且这条路的舒适度就是 两者的差值。 这样,只要枚举从每一条路开始,向前找到可以使得 起点和终点连通的路的舒适度,就可以找到答案了View Code #include<iostream>#include<algorithm>using namespace std;struct edge{ int u,v,w;}e[1001];int f[201],n,m;bool cmp(edge a,edge b){
阅读全文
摘要:题目大概意思:给定一个图,任意俩点间的最短路已知,判断该图是否存在,若不存在,则输出impossible,存在,输出可能的最少边数分析:首先,判断该图是否存在,这个很容易,对已给的图求出任意点的最短路,若存在俩点最短路与原图不同(即所给图存在更短路),则不存在;若该图存在,求出最少的边数,其实就是一个删边的过程,起始的边数是n*(n-1),若俩点之间存在其他路径长等于直接相连时的路径长,则删去,注意,要判断是否重复删边(orz,这里WA了几次);求任意俩点之间的最短路,用floyd算法,复杂度O(n^3),因为n最大为100,无压力~~View Code #include<iostrea
阅读全文
摘要:题意:有N-1个城市给首都(第N个城市)支援物资,有M条路,走每条路要耗费一定百分比(相对于这条路的起点的物资)的物资。问给定N-1个城市将要提供的物资,和每条路的消耗百分比。求能送到首都的最多的物资数量思路:求前N-1个点各自到达N是所剩物资的最大值,设dis[i]为到达i城市时所剩的物资,则变为求最长路的问题了,所以要对前N-1个节点都做一次最长路,再累加即可。要注意的地方:1)第一是消耗百分比是相对于这条路的起点,第二是无向边。因为第一点,所以不能看成反向的DIJ一次性做完,而是应该把每个点可以送到最多物资依次算出来最后相加。用Bellman松弛边,因为是无向边,而又没有保存两次边,所以
阅读全文
摘要:Bellman-ford 的变形:题意:一个游戏,要在能量大于0的情况下从room[1]走到room[n]判为赢,不然中途停止或者能量为负判为输,其中房间之间可以是回路,每个房间有自己的能量。由于是求能否到达,当然想尽可能的多增加能量,故用Bellman求最长路。而中间过程中不能使能量为零或负,故在Bellman松弛前加一条件,控制其松弛的点。最后如果能得到终点最长路大于零,则能过关,或者有正圈可以到达终点,也能过关。判断是否连通,用floyd 算法,O(n^3)#include<iostream>#include<string>#define MAXINT 99999
阅读全文
摘要:嘿嘿,跟pku 1151 差不多,都是单源最短路,这次求的是每个点往返最短时间中的最大值,就是先按pku1151一样,求往返俩次的最短路,再求出最大值即可代码基本没怎么改#include <iostream>#include<string>#include<stdlib.h>using namespace std;const int MAX = 1010;const int inf = INT_MAX;int N,m,n,num,s;typedef struct vol{ int w,//当前位置 v,//价值 value next;//下一结点的位置} V
阅读全文
摘要:这题目限制是8000ms,一看就不怎么做得下去了,但题目意思倒是很简单求源点到其他各个点之和 加上 其他各个点到源点之和的最小值建立正反两个邻接表,作正反两次最短路,SPFA逆序的情况:在初始化的时候在反向保存另一相同表 即: 1 ---> 2 13 反向后:2 ---> 1 13 要求各点到源点的距离和,即求源点到各点的距离和 所以,处理好后,只要求两次源点到各点距离和相加即可#include <iostream>#include<string>#include<stdlib.h>using namespace std;const int MA
阅读全文
摘要:多个起点,一个终点,求最短路,额,一开始三种SPFA都试了一下,用队列实现,用栈实现,唉,都悲剧的TLE了,怎么就没想到呢,把终点变成起点,就只需要调用一次SPFA了,而且,最后在遍历一下,找出路径最短的原先的起点,#include<iostream> #include<queue>#define MAXINT 9999999 #define MAXN 1010 using namespace std; int vis[MAXN],dis[MAXN],n,num,m; int root[MAXN],cou[MAXN]; struct edge { int u,w,nex
阅读全文
摘要:这题目,我差点彻底崩溃了,郁闷死了,一开始一直TLE,原来只有一个测试数据,这叫我情何以堪……后来,还发现了一个错误,就是构图时候,最大节点跟最小节点还是要标记一下比较好,我本来是默认0是最小节点的,可是在后面添加新边的时候又添加了一个0节点,唉就是Sbi+1-Sai>=Ci,这样来添加边计较保险用数组模拟队列来实现SPFA的时候,数组要绝对的足够大,我就这样RE了无数次,最后Q[maxn*10]才过的,但此时内存已经很大了不过也可以直接用STL里面的queue来做,方便很多,内存也不算很大还有用栈实现的,这个就很省内存啦为什么用栈写有时候会很快呢? 首先它很节省空间,因为最多有v-1个
阅读全文
摘要:用spfa做,额,到目前为止做的题目都几乎是模板题,三四道都是改一下输入就了事了,不过针对题目而已,还真有选择的余地,这里一个是我的,额,内存开得太大了,主要是1000*1000的矩阵来保存一个图的信息,本来很明显的得用邻接表来储存的,,而且只保存有用的边,而且加上用队列优化,快了不少呢对比一下俩个代码吧用邻接表的:#include<cstdio>#include<iostream>using namespace std;#define N 4000struct edge{ int v,next,cost; edge(int _v=0 ,int _next=0,int
阅读全文
摘要:额,还是一个路径问题,不过这次是判断是否存在负权回路,这个直接用bellman ford 算法做就行了,只要松弛次数超过n次,则证明存在负权回路这个在说benllman ford算法的时候解释的很详细了,不过现在不太敢用INT_MAX来表示最大的整数了,动不动就溢出了#include<iostream>#define MAXINT 9999999using namespace std;int n,m,w,dis[510];struct Edge{ int u,v,weight;}edge[5220];void relax(int u, int v, int weight){ if(
阅读全文
摘要:稍微修改了一下hdu1874的代码就直接过了不过 31ms 缺陷,一大缺陷FSPA版:#include<iostream>#include<string>#include<algorithm>#define MAXN 110using namespace std;int map[MAXN][MAXN]; //map[i,j]为初始输入的i到j的距离,未知的map[i,j]=INT_MAX;int dis[MAXN],Q[MAXN*100];char vst[MAXN];// 参数n表示结点数,s表示源点int SPFA(int n, int s){ // p
阅读全文
摘要:Dijkstra算法的模板题,嘻嘻,第一道最短路,模板题呀,本来幻想着1A 的,可惜呀,少了一个条件,一个很重要的条件,既然是最短路,有重边的话,当然是保存较短的一条边,结果我根本没注意到,直接覆盖了悲剧,……………………最短路径的四个算法,看了快一天了,终于有一点点的收获,多亏了大牛博客上的详解呀http://www.wutianqi.com/?p=1890 Dijkstra算法实现http://www.wutianqi.com/?p=1912 Bellman-Ford算法http://www.wutianqi.com/?p=2285 SPFA(Shortest Path Faster Al
阅读全文
1