最小环改进算法的证明
设一个环中的最大结点为k(编号最大), 与他相连的两个点为i, j, 这个环的最短长度为g[i][k]+g[k][j]+i到j的路径中所有结点编号都小于k的最短路径长度。
根据floyd的原理, 在最外层循环做了k-1次之后, dist[i][j]则代表了i到j的路径中所有结点编号都小于k的最短路径综上所述,该算法一定能找到图中最小环。
先上模板:
#include<bits/stdc++.h>
using namespace std;
int dis[111][111],e[111][111];
int n,m;
int main()
{
int a,b,c;
while(cin>>n>>m){
memset(dis,0x3f,sizeof(dis));
memset(e,0x3f,sizeof(e));
for(int i=0;i<m;i++){
cin>>a>>b>>c;
e[a][b]=c;
e[b][a]=c;
dis[a][b]=c;
dis[b][a]=c;
}
int ans=0x3f3f3f3f;
for(int k=1;k<=n;k++){
for(int i=1;i<=k-1;i++)
{
for(int j=i+1;j<=k-1;j++){
ans=min(ans,dis[i][j]+e[i][k]+e[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]);
}
}
}
if(ans==0x3f3f3f3f) cout<<"没有最小环"<<endl;
else{
cout<<"最小环长度为:"<<ans<<endl;
}
}
}
模板题:HDU1599
直接上代码:
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 105;
const int inf = 1e8;
int n,m;
int dis[maxn][maxn],mp[maxn][maxn];//dis表示最短路径,mp表示两点间直线距离(题中给出的值存入mp)
void floyd(){
int MinCost = inf;
for(int k=1;k<=n;k++){
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++)
MinCost = min(MinCost,dis[i][j]+mp[i][k]+mp[k][j]);//更新k点之前枚举ij求经过ijk的最小环
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]); //更新k点
}
if(MinCost==inf)puts("It's impossible.");
else printf("%d\n",MinCost);
}
int main()
{
while(scanf("%d%d",&n,&m) == 2){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=dis[i][j]=inf;
for(int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=min(w,mp[u][v]);
}
floyd();
}
return 0;
}