图的最小环问题

摘要:
图1的最小环问题。最小环的定义:最小环是指图中由n个节点组成的边权重和最小环。一般来说,最小环分为有向图的最小环和无向图的最小环。样本输入3312123133133112123231样本输出3这很简单。提示可能有多条边,保留权重值最低的边。
图的最小环问题

1. 最小环定义:

  • 最小环是指在一个图中,有n个节点构成的边权和最小的环(n>=3)
  • 一般来说,最小环分为有向图最小环和无向图最小环。

2. 最小环算法

  1. Dijkstra

    解法

    • uv之间有一条边长为w的边,dis(u,v)表示删除uv之间的连边之后,uv之间的最短路。
    • 那么最小环是枚举每一条边,并删除此条边后,以其中一个端点为起点跑一边单源最短路最小环的值为:min(dis(u,v)+w)
    • 时间效率为:O(m∗n∗log n) ,对稠密图来说边数 m 趋近 n2 , 所以时间效率为 O(n3log n)。
  2. Floyd

    解法

    • 记原图u,v之间边权为mp(u,v),floyd算法在外层循环到第k个点时(还没开始第k次循环),最短路数组dis中,dis(u,v)表示的是从uv且仅经过编号[1,k)区间中的点的最短路。
    • 最小环至少有三个顶点,设其中编号最大的顶点编号为w,环上与w相邻两侧的两个点为u,v,则在最外层循环枚举到k=w时,该环的长度为dis(u,v)+mp(v,w)+mp(w,u),所以在循环时候i,j只需枚举到`i更新答案即可。
    • 复杂度:O(n3)

来看一道用floyd的例题:

Description
  • 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2 ,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。
Input
  • 第一行是2个整数NM(N <= 100, M <= 1000),代表景区的个数和道路的条数。
  • 接下来的M行里,每行包括3个整数a,b,c.代表ab之间有一条通路,并且需要花费c(c <= 100)
Output
  • 对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出It's impossible.
Sample Input
3 3
1 2 1
2 3 1
1 3 1
3 3
1 2 1
1 2 3
2 3 1
Sample Output
3
It's impossible.
Hint
  • 有可能存在重边,保留权值最小那条。
Code
#include <bits/stdc++.h>
#define Inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int maxn=100+5;
LL dis[maxn][maxn],mp[maxn][maxn]; //mp表示两点间的边权,dis表示两点间的最短路
int n, m;
void Init(){	//初始化数组
    for(int i=1; i<=n; i++) for(int j=1; j<=n;j++) mp[i][j] = (i==j) ? 0 : Inf;
}  
int main(){
    while(~scanf("%d%d", &n, &m)){
		Init();//多组数据注意初始化
		for (int i=0; i<m; i++){
	        int u, v; LL w; scanf("%d%d%lld", &u, &v, &w);//两个int相加可能爆int
	        if (w < mp[u][v])//处理重边,要求最短环,肯定保留权值小的
	            mp[v][u] = mp[u][v] = w;
	    }
	    for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) dis[i][j] = mp[i][j];//初始化两点间的距离
	    LL ans = Inf;
	    for (int k=1; k<=n; k++){//枚举中间点
	        for (int i=1; i<k; i++)//枚举k的其中一个相邻点
	            for (int j=i+1; j<k; j++)//枚举k的另一相邻点
	                ans = min(ans, dis[i][j] + mp[i][k] + mp[k][j]);//保证了i,j,k不是一条链
	        for (int i=1; i<=n; i++)//这里就是求个最短路了
	            for (int j=1; j<=n; j++)
	                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
	    }
	    if (ans == Inf)
	        printf("It's impossible.
");
	    else
	        printf("%lld
", ans);
	}
    return 0;
}

免责声明:文章转载自《图的最小环问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C语言博客作业--数组DHCP服务器配置--Linux下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

小x游世界树

题源    Input 7 7 8 1 3 2 5 2 4 6 5 6 1 8 1 2 9 5 4 3 3 4 10 3 7 4 Output 1 24 一看就知道是个什么套路 记录每个点的siz , dis。在父子节点间考虑转移。 然后搞了个代码,过了个极水的样例 1 #include<stdio.h> 2 #define For(i...

最短路径算法(I)-Floyed、dijkstra

弗洛伊德算法(Floyed-Warshall) 适用范围及时间复杂度 该算法的时间复杂度为O(N^3),适用于出现负边权的情况。 可以求取最短路径或判断路径是否连通。可用于求最小环,比较两点之间的大小。 (什么??你不知道什么是负边权??戳->http://t.cn/Ef7pbu6) 核心思想 对于任意一个K点,i到j的距离有两种可能:要么经过k点,要...

Dijkstra和堆优化

Dijkstra算法 由于我之前一直记的迪杰斯特拉的翻译导致我把dijkstra写成了dijstra……所以下文#define dijstra dijkstra 我以后叫她迪杰克斯歘! Dijskra是用来在有向图或者无向图中寻找任意两个点的最小距离的算法。它相较于spfa不会死掉(spfa死了),但是无法处理带负环的图和求最长路(除非加上一些奇怪的东西,...

bzoj2330: [SCOI2011]糖果(差分约束系统)

原题链接 题目描述:幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到...