Floyd算法------------观光之旅

给定一张无向图,求图中一个至少包含3个点的环,环上的节点不重复,并且环上的边的长度之和最小。
该问题称为无向图的最小环问题。
你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。
输入格式
第一行包含两个整数N和M,表示无向图有N个点,M条边。
接下来M行,每行包含三个整数u,v,l,表示点u和点v之间有一条边,边长为l。
输出格式
输出占一行,包含最小环的所有节点(按顺序输出),如果不存在则输出’No solution.’。
数据范围
1≤N≤1001≤N≤100,

1≤M≤100001≤M≤10000,

1≤l<5001≤l<500
输入样例:
5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20

输出样例:
1 3 5 2

注意:floyd算法中k是I和j中间的一个点,这里采用变形,注意题目是让按照顺序输出,卡了好久

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, INF = 0x3f3f3f3f;
int n, m;
int d[N][N], g[N][N];
int pos[N][N];
int path[N], cnt;
void get_path(int i, int j){
 if (pos[i][j] == 0)    return;
 int k = pos[i][j];
 get_path(i, k);
 path[cnt ++] = k;
 get_path(k, j);
}
int main(){
 cin >> n >> m;
 memset(g, 0x3f, sizeof g);
 for (int i = 1; i <= n; i ++)    g[i][i] = 0;
  while(m --){
  int a, b, c;
  cin >> a >> b >> c;
  g[a][b] = g[b][a] = min(c, g[a][b]);
 }
  memcpy(d, g, sizeof d);
 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 ++)
      if ((long long)d[i][j] + g[i][k] + g[k][j] < res){
       res = d[i][j] + g[i][k] + g[k][j];
       cnt = 0;
       path[cnt ++] = i;
       path[cnt ++] = k;
       get_path(i, j);
       path[cnt ++] = j;
   }
     for (int i = 1; i <= n; i ++)
    for (int j = 1; j <= n; j ++)
          if (d[i][j] > d[i][k] + d[k][j]){
           d[i][j] = d[i][k] + d[k][j];
           pos[i][j] = k;
    }
 }
      if (res == INF) puts("No solution.");
      else{
       for (int i = 0; i < cnt; i ++)   cout << path[i] << " ";
       cout << endl;
   }
      return 0;
}
发布了164 篇原创文章 · 获赞 112 · 访问量 6787

猜你喜欢

转载自blog.csdn.net/qq_45772483/article/details/105340576
今日推荐