AcWing 344. 观光之旅 (Floyd+最小环+输出路径)

🐝 🐝 🐝
(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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值