最小环

算法:

在一个图中求出一个路径长度最小的环。首先,我们可以想到迪杰斯特拉算法,计算出 dis[src,i] + map[i][src] ,然后维护一个最大值就好了。但是这样做的话,在计算 dis[src,i] 时有可能会把 map[i][src] 包含进去,那么怎么办呢,我们可以枚举每一条边,先删掉,然后求 dis[src,i] ,再计算 dis[src,i] + map[i][src] ,这样就不会错了。但是,我们有更好的算法, floyd 算法求最小环,我们枚举一个环的起点 i 和终点j,那么 map[i][k]+map[k][j]+dp[i][j] 就是一个最小候选环,其中 dp[i][j] 是没有被比 k 大的结点松弛过,也就是说,dp[i][j]没有经过 k 结点,那么这个过程完全可以在floyd算法的三重循环下一起完成。最后在算法的过程中加入路径记录,最后就可以输出路径了。

代码:

int N,M;
int map[SIZE][SIZE];
int dp[SIZE][SIZE];
int pre[SIZE][SIZE];

int ans;
int path[SIZE];
int top;

void floyd()
{
    int i,j,k;
    for(k=1;k<=N;k++){
        int tmp;
        for(i=1;i<k;i++)
            for(j=i+1;j<k;j++){
                tmp=dp[i][j]+map[i][k]+map[k][j];
                if(tmp<ans){
                    ans=tmp;
                    top=0;
                    int p=j;
                    while(p!=i)
                        path[top++]=p,p=pre[i][p];
                    path[top++]=i;
                    path[top++]=k;
                }
            }

        for(i=1;i<=N;i++)
            for(j=1;j<=N;j++)
                if(dp[i][j]>dp[i][k]+dp[k][j])
                    dp[i][j]=dp[i][k]+dp[k][j],
                    pre[i][j]=pre[k][j];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值