AcWIng344 观光之旅(floyd求最小环)

求最小环的原理是dp的思想,我们以环中最大的节点作为断点,这样在求floyd的过程中,在更新之前,可以用i和k以及j和k相连的两条线路以及原先i和j在前k-1已经求出的最短路当作环进行比较

因为我们分割出了所有情况。而在求取方案的时候,我们设置一个pos数组,表示最短路的分割点,进行递归求取

#include<iostream>
#include<cstring>
using namespace std;
const int N=200;
const int inf=0x3f3f3f3f;
int d[N][N];
int g[N][N];
int pos[N][N];
int path[N];
int n,m;
int cnt;
void get(int l,int r){
    if(pos[l][r]==0) //到边界了,i=j
    return ;
    int x=pos[l][r];
    get(l,x);
    path[cnt++]=x;
    get(x,r);
}
int main(){
    cin>>n>>m;
    memset(d,0x3f,sizeof d);
    int i,j,k;
    for(i=1;i<=n;i++){
        d[i][i]=0;
    }
    for(i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        d[a][b]=d[b][a]=min(d[a][b],c);
    }
    int res=inf;
    memcpy(g,d,sizeof g);
    for(k=1;k<=n;k++){
        for(i=1;i<k;i++){
            for(j=i+1;j<k;j++){
                if((long long)d[i][j]+g[i][k]+g[k][j]<res){
                    cnt=0;
                    res=d[i][j]+g[i][k]+g[k][j];
                    path[cnt++]=k;
                    path[cnt++]=i;
                    get(i,j);
                    path[cnt++]=j;
                }
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                if(d[i][j]>d[i][k]+d[k][j]){
                    d[i][j]=d[i][k]+d[k][j];
                    pos[i][j]=k;
                }
            }
        }
    }
    if(res==inf)
    cout<<"No solution."<<endl;
    for(i=0;i<cnt;i++){
        cout<<path[i]<<" ";
    }
    cout<<endl;
}
View Code

 

posted @ 2020-05-05 12:01  朝暮不思  阅读(129)  评论(0编辑  收藏  举报