AcWing算法提高课 Floyd求无向图最小环

主要思路为,在Floyd过程中,找到环中最大值为k的最小环

解释:

以dp的视角看待Floyd算法,在循环到k时,已经获得了经过前k-1个点的最短路径。

设环中最大标号为k,则路径可以表示为:i->k->j->...->i

i->k和k->j为直接相连,j->...->i为通过小于标号k的点相连。

当获得到比当前记录更小的环时,即可进行更新。

更新采用递归更新,即使用pos数组记录j->...->i的中间点,并递归两边获取环上全部点。

#include<bits/stdc++.h>

#define fore(x,y,z) for(LL x=(y);x<=(z);x++)
#define forn(x,y,z) for(LL x=(y);x<(z);x++)
#define rofe(x,y,z) for(LL x=(y);x>=(z);x--)
#define rofn(x,y,z) for(LL x=(y);x>(z);x--)
#define pub push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second

using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;

const int N=110;
int n,m;
int A_M[N][N];
int dis[N][N];
int pos[N][N];
int path[N];
int cnt;
void GetPath(int i,int j)
{
    if(pos[i][j]==0)
        return;
    int k=pos[i][j];
    GetPath(i,k);
    path[cnt++]=k;
    GetPath(k,j);
}
void YD()
{

    cin>>n>>m;
    memset(A_M,0x3f,sizeof(A_M));

    fore(i,1,n) A_M[i][i]=0;
    while(m--)
    {
        int i,j,l;
        cin>>i>>j>>l;
        A_M[i][j]=A_M[j][i]=min(A_M[i][j],l);
    }
    memcpy(dis,A_M,sizeof(dis));
    int res=1e9;
    fore(k,1,n)
    {
        forn(i,1,k)
        {
            forn(j,i+1,k)
            {
               if((LL)dis[i][j]+A_M[j][k]+A_M[k][i]<res)
               {
                   res=dis[i][j]+A_M[j][k]+A_M[k][i];
                   cnt=0;
                   path[cnt++]=k;
                   path[cnt++]=i;
                   GetPath(i,j);
                   path[cnt++]=j;
               }
            }
        }
        fore(i,1,n)
        {
            fore(j,1,n)
            {
                if(dis[i][j]>dis[i][k]+dis[k][j])
                {
                    dis[i][j]=dis[i][k]+dis[k][j];
                    pos[i][j]=k;
                }
            }
        }
    }
    if(res==1e9)
        cout<<"No solution."<<endl;
    else
    {
        forn(i,0,cnt)
            cout<<path[i]<<' ';
        cout<<endl;
    }
}
 
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    //cin >> T;
    while (T--)
    {
        YD();
    }
    return 0;
}
View Code

 

posted @ 2022-09-12 19:46  80k  阅读(26)  评论(0编辑  收藏  举报