无向图的最小环问题
题目
解析
既然n<=100,我们自然会想到Floyd,事实上正解也是Floyd,只不过改一下
设a表示直接距离,b表示最短路
则建图时同时给a和b一起建,跑Floyd的时候加上这一句
for(int k=1;k<=n;k++)
{
for(int i=1;i<k-1;i++)for(int j=i+1;j<k;j++)ans=min(ans,b[i][j]+a[i][k]+a[j][k]);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b[i][j]=min(b[i][j],b[i][k]+b[k][j]);
}
可以看出,b[i][j]+a[i][k]+a[j][k]代表一个编号必定不超过k且最少有三个点(i,j,k)的环
那如果允许只有两个点呢?
for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b[i][j]=min(b[i][j],b[i][k]+b[k][j]);
for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)ans=min(ans,2*b[i][j]);
为什么呢?
这是无向图,b[i][j]=b[j][i]
code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,a[110][110],b[110][110],x,y,z,ans=0x1f1f1f1f;
int main()
{
memset(a,0x1f1f1f1f,sizeof(a));
memset(b,0x1f1f1f1f,sizeof(b));//设0x3f3f3f3f会炸
scanf("%d%d",&n,&m);
while(m--)
{
scanf("%d%d%d",&x,&y,&z);
a[x][y]=a[y][x]=b[x][y]=b[y][x]=z;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<k-1;i++)for(int j=i+1;j<k;j++)ans=min(ans,b[i][j]+a[i][k]+a[j][k]);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b[i][j]=min(b[i][j],b[i][k]+b[k][j]);
}//Floyd改
if(ans!=0x1f1f1f1f)printf("%d",ans);//没有环
else printf("No solution.");//注意这里,SSLOJ上没有句号,洛咕上有……
return 0;
}