原题链接
题目大意
在一张无向图中找到一个最小的环。
解题思路
很明显,这一题需要使用最短路。但是,求环的最短长度,就是求从自己到自己的最短长度,在最短路中,答案肯定是0。于是,我们需要换一种想法。其实,环如果拆开,可以变为多段线路,在这里,我们可以将其拆为三段:
对点
A
,
B
,
C
A,B,C
A,B,C 进行枚举,点
A
∼
B
A\sim B
A∼B 一段可以使用已经求出的最短路径,点
A
∼
C
A\sim C
A∼C 和
B
∼
C
B\sim C
B∼C可以使用输入时所存储的两点距离。
代码实现
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
long long f[110][110],Map[110][110],n,m,u,v,d,ans=0x7fffffff;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){//初始化
for(int j=1;j<=n;j++){
f[i][j]=0x7fffffff;
Map[i][j]=0x7fffffff;
}
}
for(int i=1;i<=m;i++){
cin>>u>>v>>d;
f[u][v]=d;//邻接矩阵
Map[u][v]=d;//邻接矩阵
f[v][u]=d;//邻接矩阵
Map[v][u]=d;//邻接矩阵
}
for(int k=1;k<=n;k++){//枚举C点和Floyed的中转点
for(int i=1;i<k;i++)//起点
for(int j=i+1;j<k;j++)//终点
ans=min(ans,f[i][j]+Map[i][k]+Map[k][j]);
for(int i=1;i<=n;i++)//起点
for(int j=1;j<=n;j++)//终点
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
if(ans!=0x7fffffff)
cout<<ans;
else
cout<<"No solution";
return 0;
}
样例1
输入
5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20
输出
61
样例2
输入
4 3
1 2 10
1 3 20
1 4 30
输出
No solution