观光旅游

【题目描述】

旅游区里有N个景点。两个景点之间可能存在长度为A的双向道路。

旅游区规定,每个游客的旅游线路只能是一个回路。小明来到这里旅游,希望尽量少走一些路,请你帮他求出最优路线长度。

【输入描述】

输入有多组数据,对于每组数据:

第一行输入两个正整数N、M,表示景点个数,以及有多少对景点之间存在道路(N ≤ 100,M ≤ 10000);

接下来M行,每行输入三个正整数,表示一条道路的两端的景点编号,以及这条道路的长度( ≤ 1000)。

【输出描述】

对于每组数据,如果该回路存在,则输出一个正整数,表示该回路的总长度,否则输出“No solution.”。

【样例输入】

5 7

1 4 1

1 3 300

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.

源代码:

#include<cstdio>
#include<algorithm>
#define INF 1000000 //开大了竟然会爆。
using namespace std;
int m,n,ans,i[101][101],f[101][101];
void Solve()
{
    ans=INF;
    for (int a=1;a<=n;a++) //恶心的预处理。
      for (int b=1;b<=n;b++)
        f[a][b]=f[b][a]=i[a][b]=i[b][a]=a==b?0:INF;
    for (int a=0;a<m;a++)
    {
        int t,t1,t2;
        scanf("%d%d%d",&t1,&t2,&t);
        f[t1][t2]=f[t2][t1]=i[t1][t2]=i[t2][t1]=t;
    }
    for (int a=1;a<=n;a++) //裸Floyd最小环。
    {
          for (int b=1;b<a;b++)
            for (int c=b+1;c<a;c++)
              ans=min(ans,i[b][c]+f[c][a]+f[a][b]);
          for (int b=1;b<=n;b++)
            for (int c=1;c<=n;c++)
              i[b][c]=min(i[b][c],i[b][a]+i[a][c]);
    }
    if (ans==INF)
      printf("No solution.
");
    else
      printf("%d
",ans);
}
int main()
{
    while (scanf("%d%d",&n,&m)==2)
      Solve();
    return 0;
}

/*
    解题思路:
        与Floyd相辅相成,第一层循环枚举中间点,那么中间点之前的点编号一定会比中间点的编号小。
        设当前中间点为最小环中编号最大的点,易得,在使其更新最短路径前,所掌握的信息已完全包含了最小环。
        易得,i[b][c]中没有中间点,故合法,即为:
            Length=i[b][c]+f[c][a]+f[a][b]
        定能找出最小环。
*/
原文地址:https://www.cnblogs.com/Ackermann/p/5905534.html