🐝 🐝 🐝
(1)Floyd记录路径:使用road数组记录i----->j 最短路上下一个点,如果i–>j可由i—>k ,k—>j得到,则road[i][j]=road[i][k]
(2)Floyd求解最小环:
求解环的时候,可以通过求出从u 到 v 经过中间某一些结点的最短路,但是我们得确保回来的时候,不能经过那些结点,这样我们控制回来的路上只有一点k,同时设置该点为环上的序号最大值,结合floyd的性质求解。
int mincircle = infinity;
Dist = Graph;
for(int k=0;k<nVertex;++k)
{
//新增部分:
for(int i=0;i<k;++i)
for(int j=0;j<i;++j)
mincircle = min(mincircle,Dist[i][j]+Graph[j][k]+Graph[k][i]);
//通常的 floyd 部分:
for(int i=0;i<nVertex;++i)
for(int j=0;j<i;++j)
{
int temp = Dist[i][k] + Disk[k][j];
if(temp < Dist[i][j])
Dist[i][j] = Dist[j][i] = temp;
}
}
原题:
注意输出路径的时候,在每次求出一个环之后都要即时更新路径,因为要保证i—>j中经过的点均小于k
int tag[111];
int road[111][111];//i,j路径上除j以外最后一个点,i,j
int dis[111][111],mp[111][111];
inline void solve()
{
int n,m;rd(n);rd(m);
memset(mp,0x3f,sizeof(mp));
memset(dis,0x3f,sizeof(dis));
rpp(i,m)
{
int u,v,l;rd(u);rd(v);rd(l);
dis[u][v]=dis[v][u]=mp[u][v]=mp[v][u]=min(mp[u][v],l);
road[u][v]=v,road[v][u]=u;
}
ll ans= 0x3f3f3f3f;
int cnt=-1;
rpp(k,n)
{
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
{
if(ans>0ll+dis[i][j]+mp[j][k]+mp[k][i])
{
ans=0ll+dis[i][j]+mp[j][k]+mp[k][i];
cnt=0;
for(int p=i;p!=j;p=road[p][j]) tag[++cnt]=p;
tag[++cnt]=j;tag[++cnt]=k;
}
}
rpp(i,n) rpp(j,n)
if(dis[i][k]+dis[k][j]<dis[i][j])
road[i][j]=road[i][k],dis[i][j]=dis[i][k]+dis[k][j];
}
if(cnt==-1) cout<<"No solution.\n";
else
{
rpp(i,cnt) cout<<tag[i]<<" ";
cout<<endl;
}
}