题目链接:https://vijos.org/p/1046

题目描述

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

输入

对于每组数据:
第一行有两个正整数N,M,分别表示学校的景点个数和有多少对景点之间直接有边相连。(N<=100,M<=10000)
以下M行,每行三个正整数,分别表示一条道路的两端的编号,以及这条道路的长度。

输出

对于每组数据,输出一行:
如果该回路存在,则输出一个正整数,表示该回路的总长度;否则输出“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.

解题思路

因为n很小可以直接Floyd求最小环,注意最小环ans更新的位置,每次枚举i为下家更新点,应该先尝试更新ans再更新j,k之间的最短路,我们用q.dis[j][k]来记录i,j之间最短路径,而p.dis[j][k]用来保存j,k之间的原始路径长度。
因为我们知道j,k要构成一个最小环,肯定要有两条路可走:
1.直接从j到k。
2.从j经过某个中途点i到达k。
即对于每一个i我们先尝试从这个i点对于所有的j,k点能不能得到最小环,然后我们再用这个i点尝试更新路径。
比普通Floyd多出来的部分,主要利用到的原理是当处理到i时,所有以0到k-2为中间结点的最短路径都已经确定,则这时候的环为(j到k(0<j,k<i)的最短路径)+边(i,k)+边(k,j),遍历所有的j,k找到上述式子的最小值即为在i下的最小代价环。

#include <stdio.h>
const int inf = 99999999;
struct edge {
    int dis[110][110];
}q, p;
int ans, n, m;
void Add(int u, int v, int w) {
    p.dis[u][v] = w;
}
void Floyd()
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < i; j++)
            for (int k = j + 1; k < i; k++)
                if (q.dis[j][k] + p.dis[j][i] + p.dis[i][k] < ans)
                    ans = q.dis[j][k] + p.dis[j][i] + p.dis[i][k];
        for (int j = 0; j < n; j++)
            for (int k = 0; k < n; k++)
                if (q.dis[j][k] > q.dis[j][i] + q.dis[i][k])
                    q.dis[j][k] = q.dis[j][i] + q.dis[i][k];
    }
}
int main()
{
    int u, v, w;
    while (~scanf("%d%d", &n, &m))
    {
        ans = inf;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                p.dis[i][j] = inf;
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            Add(u - 1, v - 1, w);
            Add(v - 1, u - 1, w);
        }
        q = p;
        Floyd();
        if (ans < inf)
            printf("%d\n", ans);
        else printf("No solution.\n");
    }
    return 0;
}