Floyd求最小环!(转载,非原创)

//Floyd 的 改进写法可以解决最小环问题,时间复杂度依然是 O(n^3),储存结构也是邻接矩阵

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;
         }
}

以上为网上流传的Floyd求最小环的主代码。我们发现,最下面两重循环就是Floyd原来的代码,新增的就是上面那个判环部分。一开始,我不明白,为什么要把新增的放在前面,两者的顺序能不能调换?现在的理解是这样的:在第k层循环,我们要找的是最大结点为k的环,而此时Dist数组存放的是k-1层循环结束时的经过k-1结点的最短路径,也就是说以上求出的最短路是不经过k点的,这就刚好符合我们的要求。为什么呢?假设环中结点i,j是与k直接相连,如果先求出经过k的最短路,那么会有这样一种情况,即:i到j的最短路经过k。这样的话就形成不了环,显然是错误的。当时还有一个问题,就是为什么要多开一个Dist数组呢,一个Graph不是足够了吗?其实好好想想,出现的问题和前面是一个道理。如果只开Graph,那么它里面的值就会不断改变,也会存在路径覆盖的情况,导致形成不了环或不是最小环。举个例子:假设现在进行第k层循环,i,j为枚举出来与k直接相连的边。由于此时Graph是动态的,原来根本不存在i到k的一条边,现在可能经过其它结点形成了“边”,但它未必是与k直接相连的边。以上两个问题花了我半天时间来弄懂,由于网上也没有找到关于这些问题的(可能我比较笨吧),所以要写这些东西,但又写得挺乱……

题目大意:中文题,求三个地点形成的最小环。

解决方法:之上的floyd最小环算法;

AC代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
int n,m;
int map_[1000][1000];
int dis[1000][1000];
int main()
{
    while (cin>>n>>m)
    {
        memset(map_,INF,sizeof(map_));
        for (int i=1; i<=m; i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            //cout<<a<<b<<c<<endl;
            map_[a][b]=map_[b][a]=min(c,map_[a][b]);
           // cout<<map_[a][b]<<map_[b][a]<<endl;
        }
        for (int i=1; i<=n; i++)
        {
            for (int j=1; j<=n; j++)
            {
               // cout<<map_[i][j]<<" ";
                dis[i][j]=map_[i][j];
            }//cout<<endl;;
        }
        int ans=INF;
        for (int k=1; k<=n; k++)
        {
            for (int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    if (i!=j&&j!=k&&i!=k&&map_[i][k]!=INF&&map_[k][j]!=INF&&dis[i][j]!=INF)
                    {
                        ans=min(ans,dis[i][j]+map_[j][k]+map_[k][i]);
                        //cout<<ans<<endl;
                    }
                }
            }
            for (int i=1; i<=n; i++)
            {
                for (int j=1; j<=n; j++)
                {
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                }
            }
        }
        if (ans==INF) cout<<"It‘s impossible."<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-11-25 07:46:06

Floyd求最小环!(转载,非原创)的相关文章

HDU - 1599 find the mincost route(Floyd求最小环)

find the mincost route Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status Description 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个

【BZOJ 1027】 (凸包+floyd求最小环)

[题意] 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金. [分析] 只要考虑前两个物质的比例,因为加起来等于1. 如果你看过zoj3154,就会知道这题的模型,用二元组表

多源最短路径Floyd、Floyd求最小环【模板】

Floyd算法:用来找出每对点之间的最短距离.图可以是无向图,也可以是有向图,边权可为正,也可以为负,唯一要求是不能有负环. 1.初始化:将Map[][]中的数据复制到Dist[][]中作为每对顶点之间的最短路径的初值,Pre[i][j] = i 表示 i 到 j 路径中 j 的前一节点. 2. k 从 1 到 N 循环 N 次,每次循环中,枚举图中不同的两点 i,j,如果Dist[i][j] > Dist[i][k] + Dist[k][j],则更新Dist[i][j] = Dist[i][k

HDU 1599 find the mincost route (Floyd求最小环) &gt;&gt;

Problem Description 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区.现在8600需要你帮他找一条这样的路线,并且花费越少越好. Input 第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数. 接下来的M行里,每行包括

弗洛伊德Floyd求最小环

模板: #include<bits/stdc++.h> using namespace std; const int MAXN = 110; const int INF = 0xffffff0; int temp,Map[MAXN][MAXN],Dist[MAXN][MAXN],pre[MAXN][MAXN],ans[MAXN*3]; void Solve(int i,int j,int k) { temp = 0; //回溯,存储最小环 while(i != j) { ans[temp++]

USACO 4.1 Fence Loops(Floyd求最小环)

Fence Loops The fences that surround Farmer Brown's collection of pastures have gotten out of control. They are made up of straight segments from 1 through 200 feet long that join together only at their endpoints though sometimes more than two fences

Floyd求最小环

首先求最小环有一个比较好想的方法:每次删掉一条边,看看这条边n所连的点i之间的距离(dijkstra),时间复杂度O(m*V^2*logv) 其实floyd也能完成这个功能.f[i][j][k]表示i到j在中间点为1~k的最近距离 对于一个环,我们假设i和j中只夹这一个数k,则环长为f[i][j][k-1]+map[i][k]+map[k][j],枚举一下 #include<iostream> #include<cstdio> #include<algorithm> #

BZOJ_1027_[JSOI2007]_合金_(计算几何+Floyd求最小环)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1027 共三种金属,\(m\)种材料,给出每种材料中三种金属的占比. 给出\(n\)种合金的三种金属占比.用材料做合金,问最少需要多少种材料. 分析 首先,由于三种金属的占比相加为1,所以确定了前两项,最后一项也就确定了,我们可以用二唯坐标\((x,y)\)表示前两项,这样每种材料和合金就是二维平面上的一个点. 接下来是用材料做合金. 首先来考虑用两种材料做合金,两种材料为\((x1,y1)和

poj1734(floyd求最小环)

Sightseeing trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7483   Accepted: 2827   Special Judge Description There is a travel agency in Adelton town on Zanzibar island. It has decided to offer its clients, besides many other attra