图论

【图论】tarjan割点:模板题:洛谷3388

点点圈 提交于 2019-12-02 16:15:07
割点 在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。 割点的求法 由tarjan的算法过程,我们可以得知,若一个点u为割点,则其子孙中必有dfs序比其小的点v,使low[v]<low[u],在去掉这个点u后,必然让强连通分量中的环上一点去掉,则割掉后的子图不能构成强连通分量。 模板题:洛谷3388 求割点的个数和数量 #include<bits/stdc++.h> using namespace std; const int maxn=20010; int low[maxn],dfn[maxn],iscut[maxn]; int n,m,ans; vector<int> g[maxn]; int st[maxn],top; int deep; void tarjan(int u,int fa) { int child=0; int sz=g[u].size(); dfn[u]=low[u]=++deep; for(int i=0;i<sz;i++) { int v=g[u][i]; if(!dfn[v]) { child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>dfn[u]) iscut[u]=1; } else { if(v!

【图论】Floyd找无向图最小环

六月ゝ 毕业季﹏ 提交于 2019-12-02 16:13:23
Floyd求无向图最小环 算法思想 如果若干个点形成一个环,则该环对应的有限点集V一定含有最大编号的点Kmax,按编号小到大枚举这个最大点k。 枚举时,以k为外层循环,每层循环考虑: 只经过前k-1个点的i,j间最短路径d[i][j],连接i,k的边g[i][k],连接k,j的边g[k][j],若d[i][j]+g[i][k]+g[k][j]<mn,则更新最小环的长度,同时记录路径,该环路径包含了曾经的k-1个点中的最短路上的点,也包括i,j,k三点,放入答案数组中即可。 若要统计最小环的个数,则可以在mn==d[i][j]+g[i][k]+g[k][j]时计数,要注意,如果mn在后续被更新,该计数个数要重置。 变量定义 d[i][j]:从i到j的最短路径长 g[i][j]:连接i和j的最小边长(直接相连) pos[i][j]:在Floyd中更新了i,j间最短路径的点 mn: 最小环的长度 代码 POJ 1734(模板题) #include<cstdio> #include<iostream> #include<vector> using namespace std; const int maxn=101; const int _INF=0x7fffffff; const int INF=_INF/3; int n,m; int d[maxn][maxn],g[maxn][maxn

( 图论专题 )【 最短路 】

橙三吉。 提交于 2019-12-02 15:13:12
( 图论专题 )【 最短路 】 dijkstra的堆优化(最简版本) 先了解不用堆优化的dijkstra:https://blog.csdn.net/weixin_43828245/article/details/90722389 推荐视频讲解(代码是Python写的,重点听思路):https://www.bilibili.com/video/av25829980 了解c++优先队列:https://blog.csdn.net/weixin_43828245/article/details/90742490 #include <iostream> #include <queue> #include <cstring> #define inf 0x3f3f3f using namespace std; typedef struct node { int v,date; } ty; bool operator < ( const ty &a, const ty &b ) // 自定义优先队列规则,先pop出小的来 { return a.date>b.date; // 这里和sort相反,a>b是先pop出小的 } int a[2002][2002]; int via[2002]; // 判断是否已经pop出来了 int dis[2002]; // 存放距离 int i,j,n,m;

图论--二分图最佳完美匹配(KM模板)

夙愿已清 提交于 2019-12-02 14:40:45
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 305; const int INF = 0x3f3f3f3f; int love[MAXN][MAXN]; // 记录每个妹子和每个男生的好感度 int ex_girl[MAXN]; // 每个妹子的期望值 int ex_boy[MAXN]; // 每个男生的期望值 bool vis_girl[MAXN]; // 记录每一轮匹配匹配过的女生 bool vis_boy[MAXN]; // 记录每一轮匹配匹配过的男生 int match[MAXN]; // 记录每个男生匹配到的妹子 如果没有则为-1 int slack[MAXN]; // 记录每个汉子如果能被妹子倾心最少还需要多少期望值 int N; bool dfs(int girl) { vis_girl[girl] = true; for (int boy = 0; boy < N; ++boy) { if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次 int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy]; if (gap == 0) { /

图论--传递闭包(Floyd模板)

十年热恋 提交于 2019-12-02 14:37:23
#include<iostream> #include<cstring> #include<cmath> using namespace std; int dp[105][105],in[105],out[105]; int init() { for(int i=1;i<=105;i++) { in[i]=0; out[i]=0; for(int j=1;j<=100;j++) { dp[i][j]=0; } } } int main() { long long t; cin>>t; while(t--) { init(); long long n,m; cin>>n>>m; long long flag=0; for(int i=1;i<=m;i++) { long long l,r; cin>>l>>r; dp[l][r]=1; if(l==r) flag=1; //自己排在自己前面是不可能的,直接按题意输出0 } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=(dp[i][k]&&dp[k][j]);//floyd 讨论图的连通性 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dp[i][j]==1&&dp[j][i]==1)

图论--欧拉回路(模板)

风格不统一 提交于 2019-12-02 14:35:25
int g[510][510]; stack<int> s; int d[510]; void euler(int u) { for(int v=1; v<=500; v++) { if(g[u][v]) { g[u][v]--; g[v][u]--; euler(v); s.push(v); } } } int main() { int u,v; int n; cin>>n>>m;// 点,边 for(int i=1; i<=m; i++) { cin>>u>>v; g[u][v]++; g[v][u]++; d[u]++; d[v]++; } int flag=1; int cnt=0; for(int i=n; i>=1; i--) if(d[i]%2) { flag=i; cnt++; } if(cnt>2) { cout<<"No Euler"<<endl; return 0; } euler(flag); s.push(flag); while(!s.empty()) { cout<<s.top()<<endl; s.pop(); } } 来源: https://blog.csdn.net/weixin_43627118/article/details/102775433

图论篇4——拓扑排序

允我心安 提交于 2019-12-02 13:08:32
引入 AOV网络   在 有向图 中,用顶点表示活动,用有向边<V i , V j >表示活动 i 是活动 j 的必须条件。这种有向图称为用顶点表示活动的网络(Active on vertices),简称AOV网络。 在AOV网络中,如果活动V i 必须在V j 之前进行,则存在有向边<V i , V j >,并称V i 是V j 的直接前驱,V j 是V i 的直接后继。这种前驱与后继的关系具有 传递性 和 反自反性 ,这要求AOV网络中 不能出现回路 ,即 有向环 。因此,对于给定的AOV网络, 必须先判断它是否存在有向环。 拓扑排序   检测有向环可以通过对AOV网络进行拓扑排序,该过程将各个顶点排列成一个线性有序的序列,使得AOV网络中所有的前驱和后继关系都能得到满足。 如果拓扑排序能够将AOV网络的所有顶点都排入一个拓扑有序的序列中,则说明该AOV网络中没有有向环,否则AOV网络中必然存在有向环。AOV网络的顶点的拓扑有序序列不唯一。可以将拓扑排序看做是将图中的所有节点在一条水平线上的展开,图的所有边都从左指向右。   用穿衣服的次序来描述拓扑排序,图(a)表示必须先穿某些衣服,才可以穿其他衣服,图(b)表示将拓扑排序后的有向无环图在一条水平线上展示出来。袜子和内裤属于同等级,在排序结果中谁先谁后无所谓。 算法描述 对于一个 有向无环图 (1)统计所有节点的入度

[LLL邀请赛]参观路线(图论+dfs)

ε祈祈猫儿з 提交于 2019-12-02 13:04:18
emmmm....学校的oj被查水表了,扒不到原题面,所以.... 但是我还是扒到了题面。。。 题目大意:给定一个完全图,删掉其中一些边,然后求其字典序最小的遍历顺序 有点像去年day2T1啊.... 但是数据范围如果建图的话就可以螺旋升天了。 很容易想到建反图(郑州集训233,可是这题不建反图会死) 然后想怎么遍历.... dfs序无疑,但是该怎么....跑这么多呢.... (真的很难想) solution: 删边。 可以说删边。 既然要求字典序最小,那就给它一个字典序最小:123456789 把所有点先连上,向下跑,判断这两点之间的路有没有被炸掉,要是被炸掉了,就跑到i+2那个点去,然后把路删了,连到下面去。 有些坑人,代码细节不少。 #include<iostream> #include<cstdio> #include<vector> #include<algorithm> #define rg register using namespace std; inline int read()//怕被卡加的读优 { int x=0,f=1;char s=getchar(); while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();} while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}

图论问题总结

我是研究僧i 提交于 2019-12-02 12:51:09
一,最短路问题, (一)迪杰斯特拉优先队列优化nlogn,注意要把编号和距离开结构体压入队列中,要把建反向边的思想牢记在脑子里;不能解决负环。 (二)弗洛伊德算法,对于500以内的数据可以直接用它暴力求解,还可以判断连通性问题,n三方。 (三)spfa,尽量用弗洛伊德替代,大佬都这么说,我也不知道为什么,可以解决负环问题,入队3*n时可以结束。 二,最小生成树, (一)克鲁斯卡尔算法(边集储存)和prim算法(邻接矩阵储存)。 (二)倍增算法求LCA,并维护最值,dfs完成;(同时复习。RMQ求区间最值)。 三,树链剖分, (一)dfs1,求出size(包括自己),找到自己的重儿子; (二)dfs2,先对重儿子进行编号,记录新编号和原编号的关系,记录每一个节点的top值; (三)用线段树位置区间,记得数组要开到原来的四倍!!。 (四)记得访问线段树的时候,访问的是新的编号。 (五)边权下放的情况,当top相等的时候,编号较小的那个点不算(因为记录的上一条边)。 (六)用剖分求LCA。 (七)每一条重链编号连续,每一个根节点及其子树编号连续。 四,二分图(这个应该不是特别重要) (一)最大匹配(匹配最多),完美匹配(每个点匹配完),完备匹配的概念(其中一个集合匹配完; (二)判断是否为二分图,bfs染色法,选任意节点编号为0,对儿子节点依次++,最后遍历,同一条边的两个节点的奇偶性