码迷,mamicode.com
首页 > 其他好文 > 详细

图的最小环floyed

时间:2019-04-23 21:17:46      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:statement   lse   char   div   ash   它的   起点   为什么   clu   

最优的路线

问题描述

学校里面有N个景点。两个景点之间可能直接有道路相连,用Dist[I,J]表示它的长度;否则它们之间没有直接的道路相连。这里所说的道路是没有规定方向的,也就是说,如果从I到J有直接的道路,那么从J到I也有,并且长度与之相等。学校规定:每个游客的旅游线路只能是一个回路(好霸道的规定)。也就是说,游客可以任取一个景点出发,依次经过若干个景点,最终回到起点。一天,Xiaomengxian决定到湖南师大附中旅游。由于他实在已经很累了,于是他决定尽量少走一些路。于是他想请你——一个优秀的程序员——帮他求出最优的路线。怎么样,不是很难吧?

输入文件

输入中有多组数据。

对于每组数据:

第一行有两个正整数N,M,分别表示学校的景点个数和有多少对景点之间直接有边相连。(N<=100,M<=10000)

以下M行,每行三个正整数,分别表示一条道路的两端的编号,以及这条道路的长度。

输出文件

对于每组数据,输出一行:

如果该回路存在,则输出一个正整数,表示该回路的总长度;否则输出“No solution.”(不要输出引号)

样例输入

5 6
1 4 1
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20
4 3
1 2 10
1 3 20
1 4 30

样例输出

61
No solution.

限制和约定

时间限制:1s

空间限制:128MB

 

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=1e2+5;
const int INF=1e7;
int w[maxn][maxn],d[maxn][maxn]; 
inline int read()
{
    int a=0;char x=getchar();
    while(x<0||9<x){
        x=getchar();
    }
    while(0<=x && x<=9){
        a=(a<<3)+(a<<1)+x-0;
        x=getchar();
    }
    return a;
}
int n,m;
inline void floyed(){
    int ans=INF;
    for(int k=1;k<=n;k++){
        for(int i=1;i<k;i++)
        for(int j=i+1;j<k;j++){
            ans=min(ans,d[i][j]+w[i][k]+w[k][j]);
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        }
    }
    if(ans==INF){
        printf("No solution.\n");
    }
    else printf("%d\n",ans);
}

int main()
{
    while(scanf("%d%d",&n,&m)==2){
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
        w[i][j]=d[i][j]=INF;
        }
        for(int i=1,u,v,k;i<=m;i++){
            u=read();v=read();k=read();
            w[u][v]=min(w[u][v],k);
            d[u][v]=d[v][u]=w[v][u]=w[u][v];
        }
        floyed();
    }
    return 0;
}


为什么判环时到k-1??

解释:

因为最小环中任意3个点的dis[u][v]+w[u][k]+w[k][v]都相等

而最大编号的点还是递增的

所以

for k from 1 to n

  for i from 1 to k-1

  for j from i+1 to k-1

  ans=min();

i和j的范围都合适,都能保证不会原路返回(i!=j  dis[i][j]不包括k点)

同时也不会丢失解,因为最优解中最大的点一定会被作为断点更新ans

图的最小环floyed

标签:statement   lse   char   div   ash   它的   起点   为什么   clu   

原文地址:https://www.cnblogs.com/a-blog-of-taojiayi-2003/p/10758681.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!