
图论
图论算法在计算机科学中扮演着很重要的角色,它提供了对很多问题都有效的一种简单而系统的建模方式。很多问题都可以转化为图论问题,然后用图论的基本算法加以解决。
m0_51303687
取乎其上,得乎其中;取乎其中,得乎其下;取乎其下,则无所得矣。
展开
-
做题记录 2021.8.18
思路:因为树是特殊的图,故树上距离可以用图的方法求解。本题数据量小(1<=n<=100),直接使用Floyed即可。当然也可以BFS。方法为:进行n次BFS,求出以每个点为起点的最短路,再计算以每个点为终点的最短路。代码如下:int dist[M][M];inline void bfs(int st) { bool *vis=new bool[n+1](); queue<int> q; q.push(st); while(!q.empty()) { .原创 2021-08-18 11:14:43 · 74 阅读 · 0 评论 -
做题记录 2021.08.13
对于这题,我一开始的想法是:读取完所有边的信息后,再遍历w[],对任意i,j(i<j)若w[i]!=-1&&w[j]!=-1,那么就在i,j间建立一条”虚拟“的边,最后用最小生成树求解即可,但这种方法会导致同一个码头被建造多次,因而会WA。正确做法是新建一个虚拟结点0,<0,i>间的边代表i点可以建立一个码头。最小生成树求解完后,如果发现以0为起始的点只用了一次,就说明只建造了一个码头,那就减去那个码头的花费。代码如下:#include <cstdio>.原创 2021-08-13 09:39:49 · 75 阅读 · 0 评论 -
做题记录2021.8.12
1.洛谷P1807思路:因图中有负权,所以不能使用Dijkstra,而本题求的是最长路,可以采取转化思想,将所有权值取负,转换为最短路问题。用SPFA或Bellman-ford求解。最后输出“最短路”的相反数即可。其实还有一个思路:求给定图的拓扑序,将起点1的距离设为0,这样终点n的距离即为最长路的长度。这可以当作一个定理。代码如下:void topo(int n) { queue<int> q; dist[1]=0; for(int i=1; i<=n; i++) {原创 2021-08-12 16:00:17 · 92 阅读 · 0 评论 -
学习记录 2021.8.11
最短路——Bellman-Ford和SPFA算法之前已经学了Dijkstra和Floyd算法。但前者只适用于边权均为正的情况,后者复杂度过高。如果图中存在负权,特别是如果存在负环,那么应该用如下算法:1.Bellman-Ford算法对所有边进行不超过|V|-1次判断,每次都采用类似Dijkstra的思路。如果循环次数达到|V|-1却仍在进行更新,那么就认为存在负环。如果某次没有对任何边进行更新,那么就退出。代码如下:struct edge { int from,to,wei;};vector原创 2021-08-11 16:50:00 · 90 阅读 · 0 评论 -
做题记录2021.8.7
思路:按照Kruskral算法的思路。Kruskral求的是最小生成树,也就是形成1个连通块需要的最小代价,那么我们改成形成k个连通块需要的最小代价。过程中需要记录连通块的个数,一开始为n,当减到k时即停止循环。//省略并查集和排序部分代码for(int i=0; i<m; i++) { int st=a[i].st,end=a[i].end; int r_st=Find(st),r_end=Find(end); if(r_st!=r_end) {.原创 2021-08-07 09:47:28 · 72 阅读 · 0 评论 -
做题记录2021.7.23
这题和01背包十分相似,但要求部分物品之间存在依赖关系。由于看到u,v,所以我就想用图表示依赖关系,建图完毕后对每个未被合并的结点进行DFS或BFS,并对路径上所有点的价值和价格相加最终得到两个和sum1和sum2,产生一个新的“物品”,其价值和价格分别为sum1和sum2,加入背包里面。进行DP时从新加入的第一个物品开始。后来发现完全没有必要这样做。直接使用一个并查集将“有关系”的物品合成一个大物品。注意如果合并时是fa[Find(x)]=Find(y),那就是v[Find(y)]+=v[Find.原创 2021-07-23 16:40:50 · 94 阅读 · 0 评论 -
做题记录2021.7.2
题目1链接对于这个题目,我一开始想到的是最短路,但感觉不对劲,画了一下,果然:就比如这个图,很显然通过1→2→3得到的拥挤程度最大值为3,是最小的,而路长为6,很明显最短路为4,所以按最短路的思路肯定是行不通的。细细想来,最小生成树似乎可以(毕竟在最小生成树的题单里) ,因为它的两种算法中,Prim是找任意一点的邻接边的最小值,Kruskral用的是避圈法,要用并查集。两种方法都涉及到“最小边”所以可能可以,只要把res+=G[i].w改成res=max(res,G[i].w)就行了。感觉后者更好原创 2021-07-02 15:48:27 · 91 阅读 · 0 评论 -
图论练习 2021.6.30
题目链接题目中要我们求最短路的个数。此时我们可以直接在模板中加入计数即可。如果到当前点的最短路正好是到其邻接点最短路-1,那么就可以更新到邻接点最短路的个数。但要注意加入的位置。#include <cstdio>#include <algorithm>#include <queue>#define INF 0x3f3f3f#define mp make_pairconst int MAX_NODE=1000001,MAX_EDGE=2000001;usin原创 2021-06-30 19:20:48 · 109 阅读 · 0 评论 -
图论算法-最小生成树
1.概念对连通图进行遍历,过程中所经过的边和顶点的组合可看做是一棵普通树,通常称为生成树。连通图中的生成树必须满足以下 2 个条件:包含连通图中所有的顶点;任意两顶点之间有且仅有一条通路;所有生成树中权值最小的叫做 最小生成树。对应地,非连通图中的类似概念为生成森林。2.算法1.Prim算法 1.思路:1.反正都要经过所有点,所以先选定一个起点;2.设置一个dist数组,表示以i为终点的邻接边的最小权值;3.遍历当前起点的所有邻接边,原创 2021-06-20 19:14:31 · 293 阅读 · 0 评论 -
图论算法-最短路
一.Dijkstra算法1.概述一种运用贪心策略的单源最短路径算法。2.基本思路(1)使用数组dist,G,dist[i]表示目标为顶点 i的最短路径,起始点的dist为0,其余各点为+∞;G为用链式向前星存储的图,它包括三个成员:当然,也可以用邻接矩阵等其他方式存图。(2)遍历过程中不断查找到当前点(设为cur)的最短路+与它邻接的某条边(设为i)的权值是否小于这条边的目标结点(即G[i].to)的最短路。即是否有dist[i]+G[i].weight<dist[G[i].to]。如果原创 2021-06-14 20:28:51 · 270 阅读 · 0 评论