Kuangbin带你飞 专题四 最短路径 习题报告

Kuangbin带你飞 专题四 最短路径

题目链接:https://vjudge.net/contest/182379
题解在kuangbin的博客里都有。

最短路径的dist数组含义深究

(POJ-2253)
最短路径算法并不一定是求最短路径,也可以用最短路径的思想去求其他的东西,代码上的改变就是赋予dist数组的意义不同和转移不等式的改变。
在普通最短路径里,dist[i]代表的是第i个点到起始点的最短距离,在变形中就可以赋予其他的意义,比如表示起始点与第i 个点连通的所有边中边权最小或最大。最短路径计算过程中,就是用一个一定保证是最优的点的值(dist[u])去推出一个要到的点的值(dist[v])(有些像动态规划了),这个最优值可以是距离,也可以是最小边权,我们要找的最优解。
总之,dist数组表示的是一个有意义的数据在起始点到当前点之间的最优解。

最短路径状态转移

(POJ 1797)
最短路径问题中,也要分析好状态转移,应该取大于还是小于?应该初始化为无穷大?还是0?应该在边权和上个最优解中取大还是取小?要考虑很多方面。
对于考虑方向,根据题目要求,分析从起始点到这个点应该怎么才是最优,题目有什么限制,比如:求路径上边权的最大,这样就要在初始化dist时,初始化为0或负数,表示到该点的最大边权并未计算出,初始化起点dist时,就要设为无穷大,因为没有边限制,所以,这个边界为无穷大,在比较时,就要取dist[u]和边权中较小的一个。

原图和逆图

POJ 3268
原图进行最短路径,即得起点到各点的最短路径。
逆图,即所有边的方向改为相反的方向,这时进行一次最短路径,就能得到各个点到这次起点的最短路径。
逆图中,起始点能走的边都是原本其他点到起始点的,这是起始点到其他点的最短路径,也就是其他点到起始点的最短路径。妙哉!!
两次最短路径进行加和,即得一个回路的最短路径。
因为可以用邻接矩阵建图,所以可以直接反转方向求逆图,反转方向时,一定不要重复反转,保证全部翻转的条件是只反转对角线一侧的区域,如果把所有区域都反转,则是翻转两次,等于没有反转。
也可以在建图时,建两个方向相反的图。

建模

POJ 1860
难度大的最短路径题目,可能看起来并不是求最短路径,但是,经过建模后可以通过最短路径进行求解。
有一类问题一般有如下特点:
1. 有一个起始状态;
2. 能够知道到其他点(状态)的关系,状态转移关系;
3. 求得最终状态的最优解。
在解答时,找好起始点、初始化条件、转移关系、终止点条件,然后跑最短路径就好。
例如在POJ 1860这道题中,起始点就是手里有多少钱,不再是dist[s] = 0, 而应该是dist[s] 等于初始手中的金额;初始化条件的判断,可以根据转移关系得知,因为最终要求得一个类似于较大值得东西,所以,当由前一个点经状态转移到达下一个点得到的值大于下一个点原先值时,进行转移,所以初始化就可以全为-1,表示还没有计算,也方便后面转移;终止条件,题目说判断时候能赚到钱,在最短路径,只有更有才会状态转移,正符合题意,可是,在原本的最短路径中,每个点只能被访问一次,在这里,消除visit数组,每个点可以访问多次,只要在此访问起始点时,即表示起始点的数额变大,即表示赚钱,结束最短路径即可,不结束的话,会无限下去。

读懂题意

POJ 1502
把题意读明白!把题意读明白!!把题意读明白!!!
一道很简单的题目,愣是想的特别复杂。
题意是从第一个点出发,可以同时去它所有与他相邻的节点,最终结果,就是所有点的最大值。
自己理解成每个点一次只能去一个点,并且发送时间在累加。也是醉了。2333…

传递闭包

POJ 3660
传递闭包矩阵,表示所有顶点的可达情况。也由Floyd求得。
也就确定了从一个点到另一个点有没有关系,这个关系最好是单一关系,不然可能会乱(猜的)。题目中,关系就是i与j的输赢关系,如果为1,则表示i赢j。
若一个点与其他所有点的关系都已确定(赢别人,或者被赢\输),那么这个人的名次就已知了,确定这个关系的方法就是,i->j和j->i有且仅有一个为1,就说明了这个点i和其他点j个输赢关系是确定了。答案就是这些点的总数。

正环

POJ 2240
找一条路径,能使某一个点的dist值不断增大,如果能增大一次,就能增大两次,也就是会有一个使值增大的环,也就是寻找一个正环。
可以使初始值为-1,利用最短路径spfa来判“负环”。

计算有向图中环的最短路径

POJ 1511
要在一个有向图中,起始点和终止点为同一个点的最短路径,也就是找到起始点到其他所有点和其他所有点到起始点的最短路径和。
起始点到其他点很好处理,一遍Dijkstra就可以得到。
但是其他所有点到起始点按照这种思维,并不好处理,如果所有点跑一遍Dijkstra,必超时。其实和前面的POJ 3268是一样的,在逆图跑一遍Dijkstra就可以得到其他所有点到起始点的最短路径。因为题目中点很多,所以在建图时就要建两个。
如果只是求一个点的出发再回来,不要求到达的点。在跑最短路时,把与起始点能到达的点初始化为起始点到该点的边权,如果是堆优化Dijkstra或者spfa,还要把这些点压进队列,然后跑最短路,起始点dist存的就是最小环。并且至少必经过一点。

差分约束

POJ 3159
差分约束系统,是指由一组两边各有一个变量的不等式组成的问题。
比如,此题中A不许B比他多C,定义i个糖果数量为num[i],则关系可表示为num[B]-num[A] <= C, 移项可得 num[B] <= num[A] + C ,也就是不存在num[B] > num[A]+C 的情况存在,像极了最短路中的转移关系,所以此类问题可以用最短路径求解。
差分约束,写好不等式是关键,因为这就是转移条件。
与差分约束无关的,此题是1号想使他和N号最大不同,顺着1号的约束条件跑就可以,不要想多哦。

建边

POJ 2502
创建一个存储坐标的数组,这样每一个坐标就有了一个序号,题目只给出一部分的边,还有隐藏的边,需要自己创建,而创建的有效性对程序的时间有很大的影响。
例如这一题中,若用邻接矩阵存储,两点之间只存花费时间最少的边,运行时很快的,如果用链式前向星,只能把所有的边都存储起来,空间时间都增加了很多。
这题巨恶心,输出必须%.0f才能过,%.0lfWA了几十发,毁我青春啊。

有限制条件的最短路径以及建立超级源点

POJ 1062
没有任何限制条件,只有不等式关系,就是最简单的最短路径算法,如果有了其他的限制条件,就需要对最短路径进行“改装”,以适应限制条件。创建限制条件的数组、判断限制条件的不等式等。
在这一题中,限制条件就是等级差异不能超过m,比如,我买了u号物品,再买v号物品是,我应该看这几方面:
1. 买到u号时的最高等级-v的等级是否超过m
2. v的等级-买到u号时的最低等级是否超过m
3. v的等级和1号等级之差是否超过m

如果都没有超过,那就可以转移,否则不可以。
有的题目还需要有一个初始状态的点,什么都没做的状态,通向某些点或所有点,这个点就是超级源点。
这题中,就需要一个超级源点,就是最初什么都没有买的状态,这个点到所有点的连边的边权就是不打折的价格。以超级源点为起点,跑最短路。要注意的时,超级源点没有等级,也就是任意等级都可以买,所以判断条件时,要特判超级源点。
与Kuangbin的枚举区间不同。

提取问题、抽象成最短路径

POJ 1847
算法不是问题,建模才是关键!
许多题目的糖衣做的很漂亮,需要剥去一层层的衣服,才能看清本质,找打炸弹。这就是一个建模的过程。
建模过程中,要把问题中的关系,用程序语言表达出来,能够靠上某一种算法,而最短路径建模过程,就是找到点的表示,边的表示,距离的表示,注意距离有时并不单纯是距离,可能是其他可以比较的值。还有就是转移关系,如果都能找的到,那么问题差不多就解决了。
在这道题目中,点很好找,就是一个个交汇点,边就是联通的点,那边权呢?如果本来就是指向的方向,那么就不需要拌动,也就没有耗费,如果不是指向的方向,就需要拌动一次,也就是耗费为1,边权就出来了,列表的第一个边权为0,其他为1。最小耗费,跑一遍最短路径即可。

有关集合的最短路径

HDU 4725
有的题目可能会有很多点的集合,在给出关系时,不仅给出一部分点与点之间的关系,还会给出集合内的点和其他集合点关系,比如说:一个集合的点到达相邻集合的任意一点花费为C。这类问题,就会有大量的隐藏的边,怎么处理这些隐藏的边是十分的关键,如果处理不好,势必会TLE。
最简单的思路,把所有的点根据集合的关系进行加边,很暴力,很容易TLE。
一般这类问题,需要加点加边,既然到另一个集合的花费是一样的,那么最好有个东西能够代表一个集合,然后到另一个集合的点时,就可以到这个东西来,然后这个东西还能发散到各个点,所以,就可以把集合抽象成一个点,然后,这个虚拟点和自己集合内的点进行建边,边权为0,这样就可以有虚拟点发散出去,根据题目要求,如果要求一个集合内的点不能相互到达,那么虚拟点与真实点只能建单向边,否则就会无消耗自由到达集合内的点。集合与集合之间,有的可以直接虚拟点进行建边,但有的需要真实点和虚拟点建边。
在这道题目中,就有同一层内的点不能互达的条件,所有只能虚拟点指向同一层的真实点,真实点指向相邻层的虚拟点,如果再加上虚拟点与虚拟点的双向加权边,会降低时间复杂度。

提取有用的信息

HDU 3416
题目给了很多信息,怎么把有用的信息提取出来,以方便解题是很关键的。提取有用的信息,很多题目都是不可以的,既然给了总有些用,如果理解不当,自然会WA。有用的信息可能不是直接获得的,一般也不是直接获得的,应该通过计算得到一些,或者过滤掉一些信息,以接近答案。
在这一题中,统计每条边最多走一次的最短路径条数,那么如果能把所有最短路径中的边提取出来,然后看能组成几组最短路,也就得到了答案。这里最短路径中的边是有用的边,如何把最短路径中的边提取出来是关键。具体看我的题解。

挖掘相关信息

HDU 4370
题目把问题抽象化,把一些条件更隐晦的传达出来,需要有能力把这个问题还原,或者转化成相关的问题,看到一个题目给的条件,可以看到这与最短路的关系,体现在最短路的哪里,这样做起来就有东西可做。不能只把提供了点边关系的题目当做最短路,最简单的题是直接给出单纯的点边关系,难一些的题目是抽象的、具体问题中的“点边关系”, 最难的就是,看起来没有点边关系,但是,最终是用最短路做的,也就是,最终(题解里)还是找到了点边关系,或者找到了可以跑最短路得信息,也许最后跑最短路的所有信息都是虚拟的点,利用题目给的信息做边,等等。
这一道题绝对是好题,转换思维,一个看似完全没有最短路的题目,转换到了最短路上,就是依据题目中给的三条关系,依次转化为1号点出度为1,n号点入度为1,其他点出入度相同。找最小的满足条件的解。如果满足了上面这几个条件,是否就满足了题目给的条件?答案是是的。所有的点都是虚拟的,不存在的,而边权则是题目中的矩阵,

Cij
就是i点到j点的边权,这样跑最短路就是正解,不过还差一点,1号限制了出度,但没有限制入度,n号限制了入度,但没有限制出度,所以,可能有1号点和n号点的环,但至少要各经过一个点,因为否则不满足题目条件。

差分约束找边权

POJ 3169
做题最悲哀的是,思路有了,并且是对的,但是写不出来。在做差分约束的题目时,要找好不等式关系,最好把不等式关系写成类似最短路里状态转移的形式,就是,dist[v] <= dist[u]+w, 这里是小于等于,因为是找边权,边权是合理存在的,当不合理时,也就是要转移的时候,换成大于的时候就是不合理的时候,也就是转移的时候。还要确定是单向边还是双向边,如果有负权,又加了双向边,必出负环,所以还要好好处理,做题太少,还没什么经验可说。
对做过的题,一定要好好看,不然看了题解做,做了也白做。

最短路径专题 总结

几天刷完了Kuangbin带你飞最短路径专题,虽然看了很多题解,但总归学到了很多东西,做下小小的总结。
专题题目安排的很合理,先易后难。
前面几道题学到了:
1. 最短路能解决一类问题,而不是单纯的最短路径问题,最短路径可以表示其他的具体意义以满足题目要求。在解决这种题目时,要找好转移关系,判断好初始化、边界条件,和最终的目标与过程的关系。
2. 逆图(可能还叫反图),对指定点在逆图跑最短路就能得到各个点到这个点的最短距离,很强大。可以用来求一个环的最短路径。
3. 传递闭包。可以表示点与点之间的连通关系。Floyd可以得到,貌似效率有点低啊。
4. 正环、负环。spfa_dfs判环、标记环很好用。
后面较难的题学到了:
1. 差分约束。最短路径可以解决的一类问题——差分约束系统问题,一组严格的两个变量的不等式关系,可以用最短路解决。解决时一定要找好不等式关系,确定好怎么建立边,怎么处理负环。
2. 建立超级源点。解决起点可能性有很多的一类问题,可以设一个超级源点,然后所有点与超级源点连边,从超级源点出发,一遍最短路即可得到答案。
3. 建立虚拟点。 更好的表示一个集合的点,减少边的建立,一个集合设一个虚拟点,虚拟点与自己集合的真实点建边权为0的边,然后根据题目要求,确定是虚拟点与其他真实点连边还是可以直接虚拟点虚拟点连边。
4. 还有的就是建模的题了,不管是具体的还是抽象的都要转化成最短路径问题,转化思维啊,想出来就做出来了,没想出来就GG了。
最短路径的题目,要处理好重边、负环、转移条件,找到最短路径的解决办法后,就好好考虑这几方面东西。
Kuangbin这些题的质量还是很高的,至少基本上题题不重样,有简单,有加深,循序渐进,谢前辈。
虽然很笨,还是学到了一些东西的,但愿能一直进步。

你可能感兴趣的:(ACM,图论:最短路径)