poj 1734 Floyd算求有向图的最小环

题意:旅游公司要开发一条新的路线 , 要求这是一个总路程尽可能短的环 , 并且不能只含两个城市 , 除开起点外 , 不能重复走之前走过的城市 , 输出这条路线?

Floyd算法求最小环


代码:
//用floyd算法 , 求有向图的最小环
#include
#include
#include
#include
using namespace std;

#define INF 0xfffffff
#define maxn 110

int grap[maxn][maxn] , n , m;
int dist[maxn][maxn];
int past[maxn][maxn];
int mincircle;
int path[maxn] , k1 ;

void init()
{
      int i , j;
      for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
                  grap[i][j] = INF;
}

void floyd()
{
      mincircle = INF;
      int i , j;
      for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
            {
                  dist[i][j] = grap[i][j];
                  past[i][j] = i;
            }

      for(int k = 1; k <= n; k++)  //每个点都成为一次中间点 , 和bellman-ford不一样
      {
            for(i = 1; i <= n; i++) //判断是不是最小环
                  for(j = 1; j <= n; j++)
                  {
                        if(i == j)  continue;
                        if(dist[i][j] != INF && grap[j][k]!=INF&&grap[k][i]!=INF && mincircle > dist[i][j]+grap[j][k]+grap[k][i])
                        {
                              mincircle = dist[i][j]+grap[j][k]+grap[k][i];
                              k1 = 0;
                              path[k1++] = i;
                              path[k1++] = k;
                              path[k1++] = j;
                              while(past[i][path[k1-1]] != i)
                              {
                                    path[k1] = past[i][path[k1-1]];
                                    k1 += 1;
                              }

                             
                        }
                  }

            for(i = 1; i <= n; i++) //Floyd算法
                  for(j = 1; j <= n; j++)
                  {
                        if(i == k || j == k)  continue;
                        if(dist[i][k] != INF && dist[k][j] != INF && dist[i][k]+dist[k][j]
                        {
                              dist[i][j] = dist[i][k]+dist[k][j];
                              past[i][j] = past[k][j];
                        }
                  }
      }
}

int main()
{
      while(scanf("%d %d" , &n , &m) != EOF)
      {
            init();
            int i , x , y , z;
            for(i = 1; i <= m; i++)
            {
                  scanf("%d %d %d" , &x , &y , &z);
                  if(grap[x][y] > z)
                        grap[x][y] = grap[y][x] = z;
            }

            floyd();

            if(mincircle == INF || mincircle < 0)
                  cout<<"No solution."<<endl;
            else
            {
                  printf("%d" , path[0]);
                  for(i = 1; i < k1; i++)
                        printf(" %d" , path[i]);
                  cout<<endl;
            }
      }
      return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值