图论

ZROI 19.07.30 简单图论/kk

断了今生、忘了曾经 提交于 2019-11-27 20:30:32
1.最短路 NOI2019 D2T1 我被这题送Fe了/lb 只有zz才会写二维线段树,比如我。 实际上你只需要矩形取min就可以。 kd-tree可以随便过,最慢的点 \(0.1s\) 。 另外一种简单做法是把边压到堆里,每次找到的最小(出发点+边权)的边一定是最优的,然后清空对应的矩形,线段树套set或者并查集都可以过。(stO _rqy Claris Orz) \(n\) 个点, \(m\) 条边的DAG,求删去每个点后 \(1\) 到 \(n\) 最短路。 \(n,m \leq 3\times 10^5\) 。 拓扑排序之后,对每个点 \(x\) 预处理出 \(f_x,g_x\) ,分别表示 \(1->x\) 和 \(x->n\) 的最短路。 按照拓扑序考虑每个点 \(x\) ,同时维护两个集合 \(A,B\) ,分别表示拓扑序在 \(x\) 前、后的点。 这样答案一定形如$f_a+g_b+(a, b), a \in A,b\in B $。 用堆维护上述结构,当 \(x\) 转移到 \(x+1\) 时,只需把 \(x\) 加入 \(A\) ,并把 \(x+1\) 从 \(B\) 中移除,并处理相应影响即可。 \(n\) 个点, \(m\) 条边的有向图,计算每个点传递闭包大小,允许误差,最多差两倍。 \(n,m\leq 2\times 10^5\) 。 SD省集讲过…

图论算法

霸气de小男生 提交于 2019-11-27 19:12:16
提供一些常用图论算法的链接:   最短路径算法总结:https://zhuanlan.zhihu.com/p/33162490   松弛技术介绍(某些最短路径算法的手段):https://www.cnblogs.com/Ash-ly/p/5789746.html    来源: https://www.cnblogs.com/BUAA-Wander/p/11373674.html

图论——一个迷人的世界

喜欢而已 提交于 2019-11-27 17:53:26
虽然不允许我们看透自然界本质的秘密,从而认识现象的真实原因,但仍可能发生这样的情形:一定的虚构假设足以解释许多现象。 ——莱昂哈德·欧拉 起源 说到图论,不得不说数学大神欧拉了,图论起源于一个非常经典的问题——柯尼斯堡七桥问题。 在18世纪初普鲁士柯尼斯堡有一条大河,河中有两个小岛。全城被大河分割成四块陆地,河上架有七座桥,把四块陆地联系起来(如上图)。当时许多市民都在思索一个问题:一个散步者能否从某一陆地出发,不重复地经过每座桥一次,最后回到原来的出发地。 欧拉把七桥问题进行了数学的抽象。用A、B、C、D四个点表示四块陆地,用两点间的一条线表示连接两块陆地之间的一座桥,就得到如下图所示的一个由四个点和七条线组成的图形。 这样,七桥问题就转化为一个抽象图形是否可以“一笔画”的问题,即笔不准离开纸,一口气画成整个图形;且每一条线只许画一次,不得重复。这样的图形能不能一笔画呢? 答案是不能。 因为除了起点和终点之外,我们把其余的点称为中间点。如果一个图可以一笔画的话,对于每一个中间点来说,当画笔沿某条线到达这一点时,必定要沿另一条线离开这点,并且进入这点几次,就要离开这点几次,一进一出,两两配对,所以从这点发出的线必然要是偶数条。因此,一个图形能否一笔画必须满足如下两个条件: 1. 图形必须是连通的。 2. 图中的“奇点”个数是0或2。 注意这里的“奇点”指的是每个顶点连的边的个数

图论 —— 图的连通性 —— 传递闭包

主宰稳场 提交于 2019-11-27 14:58:24
【概述】 传递闭包 :对于一个节点 i,如果 j 能到 i,i 能到 k,那么 j 就能到 k,求传递闭包,就是把图中所有满足这样传递性的节点计算出来,计算完成后,就知道任意两个节点之间是否相连。 简单来说,传递闭包是一种关于连通性的算法,其是指所有点的所能到达的点集。 【传递闭包的计算】 Floyd 可以用来判断图中两点是否连通,在求连通性的同时,可以进行传递闭包计算。 对于一个没有边权的图,可将相邻两点距离设为 dis[i][j]=true,不相邻的两点距离设为 dis[i][j]=false,而后进行 Floyd 算法即可。 for(int k=1;k<=n;k++)//第一重循环为i→j的中间点k for(int i=1;i<=n;i++)//第二重循环为起点i for(int j=1;j<=n;j++)//第三重循环为终点j if(dis[i][j]>dis[i][k]+dis[k][j])//如果i→k的距离加上k→j的距离小于i→j的距离 if(dis[i][k]&&dis[k][j])//更新最短路径 dis[i][j]=true; 来源: https://blog.csdn.net/u011815404/article/details/99688748

DP&图论 DAY 1 上午

吃可爱长大的小学妹 提交于 2019-11-27 09:27:49
上接: DP&图论 DAY 1 上午 这两个题本质是一个亚子,所以放一起啦 DPDPDPDPDPDPDPDP P1115 最大子段和 题解 因为题目要求的是一段连续的区间 ,所以前缀和搞暴力??? 我们设置数组 f[ i ] 表示以 a[ i ] 结尾的最大连续子段和 那么转移??? 1.接着上一段,继续构成一段连续的子段 continue the old life 2.自成一段 和过去 say goodbye 转移方程: ans记录最大值就好啦 代码 #include<bits/stdc++.h> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=2e5+10; int n,ans; int a[maxn]; int f[maxn]; int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(); f[0]=0;f[1]

DP&图论 DAY 1 上午

孤者浪人 提交于 2019-11-27 09:20:23
上接: DP&图论 DAY 1 上午 P3183 [HAOI2016]食物链 题解 ◦ 给定n个点m条边的有向无环食物网,求其中有多少条极长食物链。 ◦ n<=10^5,m<=2*10^5 >Solution ◦ 拓扑图dp经典题 ◦ 设f[u]为以节点u为终点的食物链数量。 ◦ 按照拓扑序的顺序转移即可。 处理的时候有些小细节: 1.记录每个点有多少入度:方便topsort 2.有多少出度:出度为0的非单点就是一条食物链的结束,这里可以用一个数组 vis 打标记(万一你记上单点了怎么办QAQ) 3.拓扑序转移:食物链起点的 f[u] 标记为 1 ,不然你以后咋转移??? 代码 #include<iostream> #include<cstdlib> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0'

图论基础

你离开我真会死。 提交于 2019-11-27 08:23:25
图 对于图的遍历,可以用 邻接表 和 邻接矩阵 来实现。 因为图不同于树结构,图是存在非连续的。所以图无法运用链式结构。 图又有4种情况,分别对应有无权值,有无方向 有权无向图 有权有向图 无权无向图 无权有向图 图的表示方法 邻接表和邻接矩阵 运用邻接表: int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); 因为图的各个区域的点的个数不同,所有无法用统一的二维数组,应该用向量数组 运用邻接矩阵: int u,v; scanf("%d%d",&u,&v); g[u][v]=1; g[u][v]=1; 两个点如果相互连接的话,其邻接矩阵的值就是1 在无向图里要两个都进行赋值1,而在有向图里就只需要赋值一次 所有在无向图里浪费了一半的空间 连通分量模型---求无向图组成的图的个数 对图进行遍历,求有几个区域 思路: 构建向量数组和颜色数组 向量数组用于储存关系,每个向量的头结点代表头,之后的表示与头结点相互连接的边 颜色数组用于存储颜色数值,不同的区域具有不同的颜色,相互连接,可以传递的结点具有相同的颜色数值 无向图,所以a对b,b也对a 建立向量数组,存储后,对颜色初始化 开始对n个结点查询,只要遇到color为初始值的结点就进行该结点的dfs 在dfs中运用栈

图论学习笔记

邮差的信 提交于 2019-11-27 07:14:18
最小生成树 Kruskal \(kruskal\) ,一种求最小生成树的算法,其思想与贪心有些相似,具体做法为:、 将边按照边权由小到大排序,每次拿出权值最小的一条边,看它连接的两个顶点是否在同一个连通块中(可以用并查集维护),如果在的话就不使用他,否则就加入生成树,一直加入到边数为 \(n - 1\) 结束 如何证明? 要我说我也说不明白,还是直接上图吧 图片来自: https://blog.csdn.net/weixin_43272781/article/details/83589394 复杂度: \(O(mlogm)\) 代码实现: #include <cmath> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; inline int read() { char c = getchar(); int x = 0, f = 1; for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1; for( ; isdigit(c); c = getchar()) x = (x <<3) + (x << 1) + (c ^ 48); return x * f; } const int N = 5011; const int M

图论 test solution

旧巷老猫 提交于 2019-11-27 07:01:09
图论 test solution T1:潜伏 题目背景 小悠回家之后,跟着母亲看了很多抗日神剧,其中不乏一些谍战片。 题目描述 解放前夕,北平城内潜伏着若干名地下党员,他们居住在城市的不同位置。现在身为地下党第一指挥官的你,想知道地下党员之间的最小通信距离,即从某一地下党员住处前往另一地下党员住处的距离的最小值。 我们可以将北平城视为一张N个点M条边的无向图,每条边连接两个点 ,且长度为 \(w_i\) 。 输入格式 每个测试点包含多组数据。 第一行,给出数据组数 ,之后依次输入每组数据。 每组数据的第一行,N,M,K,分别表示点数,边数,地下党员数。 之后M行,每 \(u_i,v_i,w_i\) 表示第i条边。 之后一行,K个整数代表地下党员所在结点。 结点编号为1到N,保证N>=K。 输出格式 对于每组数据,输出一行一个整数,表示地下党员之间的最小通信距离。 如果最小通信距离为∞,请输出-1代替。 样例输入 3 5 10 3 1 3 437 1 2 282 1 5 328 1 2 519 1 2 990 2 3 837 2 4 267 2 3 502 3 5 613 4 5 132 1 3 4 10 13 4 1 6 484 1 3 342 2 3 695 2 3 791 2 8 974 3 9 526 4 9 584 4 7 550 5 9 914 6 7 444 6 8

图论&线性基(?)(8.12)

∥☆過路亽.° 提交于 2019-11-27 05:22:39
边没有负权,最短路最多只有n条边 很暴力的思想: 先跑一遍最短路,找出最短路上的边,枚举每条边,翻倍,放进原图再跑一遍。取最大值 好熟悉啊 分层建图,建k层 每层内部是原图 若原图中u到v有连边,则由本层的u向下一层的v连一条边权为0的单向边 当然对于某些duliu的图(比如边数<k),用不完k次机会,所以我们还要在本层的u向下一层的u连一条边权为0的边 跑第一层的1到第k层的N的最短路 可能是唯一的 代码: #include<bits/stdc++.h> #define ll long long using namespace std; inline int read() { char ch=getchar(); int x=0;bool f=0; while(ch<'0'||ch>'9') { if(ch=='-')f=1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); } return f?-x:x; } int n,m,k,head[2000009],cnt; struct Ed { int to,dis,nxt; }edge[20000009]; void add(int fr,int to,int dis) { cnt++; edge[cnt].to=to