如题,这道题让我们求出一个 无 向 图 的 最 小 环 。 \color{blue}{无向图的最小环。} 无向图的最小环。
解题思路:
这算是一道板子题了吧,对于无向图的最小环问题,我们需要用到 Floyd \operatorname{Floyd} Floyd算法。
我们考虑一下 Floyd \operatorname{Floyd} Floyd算法的实现过程。它是一个 O ( n 3 ) O(n^3) O(n3)的的算法,运行过程可以看成动态规划。
for(int k=1;k<=n;k++)
{
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]);
}
}
}
当 Floyd \operatorname{Floyd} Floyd算法最外层执行到第 k k k层时,我们实际上已经求出了前 k − 1 k-1 k−1个点的全源最短路径。这时我们需要从这 k − 1 k-1 k−1个点中选择两个点 i 、 j i、j i、j,这时就得到了经过 i , j , k i,j,k i,j,k三个点的最小环。
枚举更新答案即可。
A C C o d e : AC\space Code: AC Code:
#include<bits/stdc++.h>
using namespace std;
int d[128][128],a[128][128];
int n,m,ans=1e8;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
d[i][j]=1e8;
a[i][j]=1e8;
}
}
for(int i=1;i<=n;i++) d[i][i]=0,a[i][i]=0;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
a[u][v]=min(w,a[u][v]);
a[v][u]=min(w,a[v][u]);
d[u][v]=min(w,d[u][v]);
d[v][u]=min(w,d[v][u]);
}
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]+a[i][k]+a[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]);
d[j][i]=d[i][j];
}
}
}
if(ans==1e8) cout<<"No solution"<<endl;
else cout<<ans<<endl;
return 0;
}
如果是只背上了代码的话,这道题肯定做不出或很难做出来,我们要着重理解算法实现的过程,方能以不变应万变。