专栏文章
一些有关图论的模板。
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min20q6c
- 此快照首次捕获于
- 2025/12/01 19:16 3 个月前
- 此快照最后确认于
- 2025/12/01 19:16 3 个月前
最短路
dijkstra
CPPmemset(d,0x3f,sizeof(d));
priority_queue< pair<int,int> > q;
q.push(make_pair(0,s));
d[s]=0;
while(!q.empty){
int u=q.top().second;
q.pop();
if(f[u]) continue;
f[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[v]>d[u]+e[i].w){
d[v]=d[u]+e[i].w;
if(!f[v]) q.push(make_pair(-d[v],v));
}
}
}
SPFA
CPPmemset(d,0x3f,sizeof(d));
d[s]=0,f[s]=1;
queue<int> q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop(),f[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[v]>d[u]+e[i].w){
d[v]=d[u]+e[i].w;
if(!f[v]){
q.push(v);
f[v]=1;
}
}
}
}
次短路
- 求最短路过程中顺带更新次短路。(可重复走边须 SPFA )
- 起点、终点各跑一次最短路,枚举各点。次短路即为某一条边长度 + 起点到一个端点最短 + 终点到另一端点最短。
有关连通性
Tarjan强连通分量
记录强连通分量个数, 时间戳, 返祖边可追溯最早时间戳。
是否在栈中, SCC 染色。
CPPint cnt,scc,dfn[],low[],f[],col[];
stack<int> s;
void Tarjan(int u){
dfn[u]=low[u]=++cnt;
s.push(u),f[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(f[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
scc++;
int x=-1;
while(x!=u){
x=s.top();
s.pop();
f[x]=0;
col[x]=u;
}
}
}
割点
- 为树根,且子树数量 。
- 不为树根,存在树枝边 满足 。
统计 dfs 树中 的树枝边数, 储存割点, 为割点数量。
CPPint cnt,dfn[],low[],root,c[];
void Tarjan(int u,int fr){
dfn[u]=low[u]=++cnt;
int tmp=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
tmp++;
Tarjan(v);
low[u]=min(low[u],low[v]);
if((u==root && tmp>1) || (u!=root && dfn[u]<=low[v])){
if(!c[u]) c[0]++;
c[u]=1;
}
}else if(v!=fr){
low[u]=min(low[u],dfn[v]);
}
}
}
点双连通分量
-
Tarjan 找割点并把 dfs 遍历点入栈。找到割点就弹栈直到弹出割点。弹出点即为该点双连通分量节点。割点重新入栈。dfs 结束时将栈弹空。所弹出点也为一个点双连通分量。
-
省略根节点判断,将割点判断条件直接改为 。同上进行入栈弹栈(发现孤立点或符合条件点)。
割边(桥)
存在树枝边,满足 。
CPPint cnt,dfn[],low[];
vector<int> b[];
void Tarjan(int u,int fr){
dfn[u]=low[u]=++cnt;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
tmp++;
Tarjan(v);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v]){
if(u<v) b[u].push_back(v);
else b[v].push_back(u);
}
}else if(v!=fr){
low[u]=min(low[u],dfn[v]);
}
}
}
边双连通分量
-
Tarjan 找桥,dfs 点入栈。找到桥就弹栈,直至栈顶为 dfs 树父节点。dfs 结束后将栈弹空。
-
将无向图看作有向图,禁止走同一无向边拆分出的回边。寻找该有向图 scc。scc 即为边双连通分量。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...