【图论】Floyd求最小环

本文详细探讨了如何使用Floyd算法解决图论中的最小环问题,结合具体实例CF1205B,深入解析算法实现过程和关键步骤,帮助读者理解并掌握这一算法在图论中的应用。

CF1205B:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define ll long long
#define inf 1e8+10
using namespace std;
const int N=110000;
int n;
ll a[N];
int dis[250][250],mp[250][250];
void build(){
	for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++){
      		if((a[i]&a[j])&&i!=j)
        		dis[i][j]=mp[i][j]=1;
      		else
        		dis[i][j]=mp[i][j]=inf;
    	}
  	}
}
int flyod(){
	int res=inf;
	for(int k=1;k<=n;k++){
		for(int i=1;i<k;i++){
    		for(int j=i+1;j<k;j++)
        		res=min(res,dis[i][j]+dis[i][k]+dis[k][j]);
    }
    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]);
    	}
    }
    return res;
}

int main()
{
	ll x;
	int cnt=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
    	scanf("%I64d",&x);
    	if(x!=0) a[++cnt]=x;
	}
  	n=cnt;
  	if(n>=130) printf("3\n");
  	else{
    	build();
    	int res=flyod();
    	if(res>n) printf("-1\n");
    	else printf("%d\n",res);
  	}
  	return 0;
}
### 有向图中的最小环算法 在有向图中寻找最小环(即权重之和最小的环)是一个常见的图论问题,广泛应用于网络分析、路径优化等领域。针对有向图的最小环问题,可以采用多种方法进行解,包括基于 **Floyd-Warshall 算法** 的改进方法、**深度优先搜索(DFS)** 以及 **Bellman-Ford 算法** 的变种等。 #### 使用 Floyd-Warshall 算法最小环 Floyd-Warshall 算法是一种经典的动态规划算法,用于计算所有点对之间的最短路径。在有向图中,可以通过修改该算法来寻找最小环。 算法步骤如下: 1. 初始化距离矩阵 `dis[i][j]`,其中 `dis[i][j]` 表示从点 `i` 到点 `j` 的最短路径。 2. 对于每个中间点 `k`,更新所有点对 `(i, j)` 的最短路径。 3. 在每次更新前,检查是否存在环:`dis[i][j] + map[j][k] + map[k][i]`,如果该值小于当前最小环,则更新最小环。 ```python # Floyd-Warshall 算法扩展用于最小环查找 def find_min_cycle(n, graph): import sys INF = sys.maxsize dis = [[INF] * n for _ in range(n)] for i in range(n): for j in range(n): dis[i][j] = graph[i][j] min_cycle = INF for k in range(n): for i in range(n): for j in range(n): if dis[i][j] + graph[j][k] + graph[k][i] < min_cycle: min_cycle = dis[i][j] + graph[j][k] + graph[k][i] # 更新最短路径 for i in range(n): for j in range(n): if dis[i][j] > dis[i][k] + dis[k][j]: dis[i][j] = dis[i][k] + dis[k][j] return min_cycle if min_cycle != INF else -1 ``` 该方法的时间复杂度为 $ O(n^3) $,适用于节点数较少的图[^2]。 #### 深度优先搜索(DFS)方法 对于稀疏图,可以采用深度优先搜索的方式遍历图,记录访问路径,当发现回边时判断是否形成环,并计算环的权重和。 ```python def dfs_cycle_detection(graph, visited, path, node, start, min_cycle): visited[node] = True path.append(node) for neighbor in range(len(graph)): if graph[node][neighbor] != 0: if not visited[neighbor]: dfs_cycle_detection(graph, visited, path, neighbor, start, min_cycle) elif neighbor == start and len(path) > 1: cycle_weight = sum(graph[path[i]][path[(i+1) % len(path)]] for i in range(len(path))) if cycle_weight < min_cycle[0]: min_cycle[0] = cycle_weight path.pop() visited[node] = False def find_min_cycle_dfs(graph): n = len(graph) visited = [False] * n min_cycle = [float('inf')] for i in range(n): dfs_cycle_detection(graph, visited, [], i, i, min_cycle) return min_cycle[0] if min_cycle[0] != float('inf') else -1 ``` 该方法适用于稀疏图,但在稠密图中效率较低。 #### Bellman-Ford 算法扩展 Bellman-Ford 算法可以检测图中的负权环,也可以扩展用于寻找最小正权环。通过多次松弛操作,可以判断是否存在环并计算最小环的权重。 ```python def bellman_ford_min_cycle(graph, n): min_cycle = float('inf') for s in range(n): dist = [float('inf')] * n dist[s] = 0 for _ in range(n-1): for u in range(n): for v in range(n): if graph[u][v] != float('inf') and dist[u] + graph[u][v] < dist[v]: dist[v] = dist[u] + graph[u][v] # 检查环 for u in range(n): for v in range(n): if graph[u][v] != float('inf') and dist[u] + graph[u][v] < dist[v]: cycle_len = graph[u][v] current = u while True: next_node = -1 for i in range(n): if graph[current][i] != float('inf') and dist[current] + graph[current][i] == dist[i]: next_node = i break if next_node == -1 or current == u: break cycle_len += graph[current][next_node] current = next_node min_cycle = min(min_cycle, cycle_len) return min_cycle if min_cycle != float('inf') else -1 ``` 该方法适用于存在负权边的图,但实现较为复杂。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值