传送门
关于最小环的讲解在这里。
这篇题解主要讲一下怎么储存边。
我们用 way w a y 数组来记录转移时候的,得到最优的 disti,j d i s t i , j 所用的 disti,k+distk,j d i s t i , k + d i s t k , j 中的 k k 。
那么当 wayi,j=0 w a y i , j = 0 时说明本来在原图中直接走 ei,j e i , j 就已经是最优的方案了
那么我们可以利用 way w a y 数组递归处理出整个环,具体方法如下
1.递归处理 i−>wayi,j i − > w a y i , j 的路径
2.将 wayi,j w a y i , j 加入队列
3.递归处理 wayi,j−>j w a y i , j − > j 的路径
代码:
#include
#include
#include
#include
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define rank Rank
inline
ll getint(){
re ll num=0;
re char c;
while(!isdigit(c=gc()));
while(isdigit(c))num=(num<<1)+(num<<3)+(c^48),c=gc();
return num;
}
inline
void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=(a-a/10*10)^48,a/=10;
while(ch[0])pc(ch[ch[0]--]);
}
int n,m;
int way[101][101];
int ans=0x3f3f3f3f;
int dist[101][101];
int a[101][101];
int q[10001],qn;
inline
void getway(int u,int v){
if(!way[u][v])return;
getway(u,way[u][v]);
q[++qn]=way[u][v];
getway(way[u][v],v);
}
signed main(){
memset(a,0x3f,sizeof a);
n=getint();
m=getint();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint(),val=getint();
a[u][v]=a[v][u]=min(a[u][v],val);
}
memcpy(dist,a,sizeof a);
for(int re k=1;k<=n;++k){
for(int re i=1;ifor(int re j=i+1;jif(ans>(ll)dist[i][j]+a[j][k]+a[k][i]){
ans=dist[i][j]+a[j][k]+a[k][i];
qn=0;
q[++qn]=i;
getway(i,j);
q[++qn]=j;
q[++qn]=k;
}
}
}
for(int re i=1;i<=n;++i){
if(i!=k)
for(int re j=1;j<=n;++j){
if(j!=k&&j!=i)
if(dist[i][j]>dist[i][k]+dist[k][j]){
dist[i][j]=dist[i][k]+dist[k][j];
way[i][j]=k;
}
}
}
}
if(ans==0x3f3f3f3f)puts("No solution.");
else for(int re i=1;i<=qn;++i)outint(q[i]),pc(' ');
return 0;
}