最小环问题总结(有向,无向,经过某一点)
发布日期:2021-05-10 11:28:58 浏览次数:18 分类:精选文章

本文共 1671 字,大约阅读时间需要 5 分钟。

最小环

顾名思义,最小环即为带权图中最短的环路

算法

主要是floyd和dij两种

Floyd

floyd三层循环中,最外层k循环代表用上第k个点的最短路,在刚开始时,所有节点最短路中都是仅包含前k-1个节点的,

我们在floyd跑带有k节点的循环前进行操作,枚举i,j。i-j-k-i为一个可能的环路。其中i-j我们用跑出的dis数组来表示,因为floyd性质确保了i-j的最短路中没有k节点存在,之后j-k和k-i我们用他们之间本来的边来表示,更新答案。

代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#define endl "\n"#define int long long//#define double long doubleusing namespace std; typedef long long ll; const int maxn=150; const int inf=0x1f1f1f1f1f1f1f1f;//1f因为最小环三个数相加3f会爆 int n,m; int mp[maxn][maxn],dis[maxn][maxn]; signed main(){ IOS cin>>n>>m; memset(dis,0x1f,sizeof dis); memset(mp,0x1f,sizeof mp); for(int i=1;i<=n;i++) dis[i][i]=mp[i][i]=0; while(m--){ int u,v,w; cin>>u>>v>>w; mp[v][u]=mp[u][v]=min(mp[u][v],w); dis[v][u]=dis[u][v]=min(dis[u][v],w); } int ans=inf; for(int k=1;k<=n;k++){ //这时已经跑出了包含前k-1个点的最短路,那么我们枚举前k-1个点 //用i-j最短路+i-k边+k-j边更新答案。 for(int i=1;i
迪杰斯特拉

这个算法主要用于以下情况:

  • 无向图最小环
  • 求经过某一顶点的最小环

若求某一顶点s的最小环,就把s所连的点都加入队列,当然这些点的dis也就是边长(相当于手动处理队列取出s的情况),之后将dis[S]设为inf,当s取出时,即找到了最小环。

对于全图最小环,枚举一遍取min即可

注意不要用这个算法求无向图最小环,不然会变成s走向最近的节点,再原路返回,答案变成了最短边的两倍。

代码

找不到例题,写了个大概意思

void solve(int s){   		memset(dis,0x3f,sizeof(dis));		priority_queue

,greater

> q; for(int i=1;i<=n;i++){ if(i==s) continue; if(mp[s][i]!=inf){ dis[i]=mp[s][i]; q.push({ dis[i],i}); } } dis[s]=inf; while(!q.empty()){ P p=q.top(); q.pop(); int u=p.second; if(dis[u]

dis[u]+mp[u][i]){ dis[i]=dis[u]+mp[u][i]; q.push(P(dis[i],i)); } } } }

上一篇:中国地质大学 数据结构-二叉树作业
下一篇:CodeForces - 1443D Extreme Subtraction 差分应用

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2025年04月29日 13时07分54秒