题解:P6175 无向图的最小环问题
注意到数据范围
Floyd 算法
这是一种基于 DP 用于求解图上任意两点间最短路的算法。设
实际实现时可以滚动数组优化掉第一维,时间复杂度
for(int k=1;k<=n;k++)
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]);
那么我们如何利用 Floyd 求解最小环呢?
在算法中第一层循环枚举到
代码:
#define ll long long
const int _mxn=1000+5;
int n,m;
ll g[_mxn][_mxn],dis[_mxn][_mxn],ans=1e18;
int main()
{
___();
cin>>n>>m;
memset(dis,0x1f,sizeof(dis));//不能设 0x3f,因为 0x3f3f3f3f3f3f3f3f*3 会爆 long long
memset(g,0x1f,sizeof(g));
for(int i=1;i<=n;i++)
g[i][i]=dis[i][i]=0;
while(m--)
{
int u,v;
ll w;
cin>>u>>v>>w;
w=min(w,g[u][v]);//要判重边
g[u][v]=g[v][u]=dis[u][v]=dis[v][u]=w;
}
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,dis[i][j]+g[i][k]+g[k][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
ans==1e18?cout<<"No solution."<<endl:cout<<ans<<endl;
return 0;
}