麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢相关的知识,希望对你有一定的参考价值。

RT
这个需要记录最小环上的点....

我用的是Dijsktra算法进行的计算。假设一个环中有两个顶点A,B,那么走完这个环的最小路程是从A到B的最短路+去掉A到B的最短路上的所有路径后的A到B(B到A)的最短路(就相当于是从A走到B再走到A的最短路)

因此,在外层枚举A,算出A到各个点的最短路,同时记下路径。然后枚举每一个B,删掉A到B上最短路径所经过的边,再算一次A到B的最短路径,然后两者相加,求得一个环的最短路。最后找一个最小的环的长度,输出即可。时间复杂度到了O(n^4),所以我有一组花了0.9s.

但是这道题的难点在于那个BT的INPUT-------从来都没有见过的图的输入方式:告诉的是边与边的关系。

我是这样解决的:找出所有的边的两个端点(不管是否重复),并把这些端点连了哪些边记录下来。然后去掉重复的顶点,剩下的就是图的顶点。接着通过枚举寻找任意两个顶点是否都连了相同的边,如果连了,说明这两个顶点就是被这条边所连,因此就可以在邻接矩阵中记录下来。时间复杂度O(n^3)

这一题是我一次AC的。。。难得在USACO Cheapter4 里面一次AC哈。。

Cherry还有更好的O(n^3)的算法,我也不知道怎么做的。感兴趣的去看一下子。
参考技术A 显然该无向图存在连通分支。对每个连通分支单独进行考虑。
对于一个连通图,任取一个它的生成树(有算法可以完成这项操作),连通分支中除过这些树枝剩下的边我们称作弦,每一条弦对应该连通图的一个基本回路,无向图的所有回路都可以表示成这些基本回路的直和(边集的并,去掉公共边),所以最小回路一定在这些基本回路里产生。我们现在把这些弦一条一条往里加就可以了。加入一条弦,立即产生一个基本回路,计算此回路边数并记录在一个数组里。去掉此弦,加入另一条弦,会有另一个回路产生,计算边数,保存。把所有的弦都试一遍,得到一个数组,取最小元素对应的弦,把弦加进生成树,就得到最小回路。这样的算法很节省空间。可以得到所有最小回路。本回答被提问者采纳
参考技术B 这是你们竞赛的题目吧?我回答了就不公平了。

poj1734(求最小环)

4923: Poj1734 Sightseeing trip

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 15  Solved: 6
[Submit][Status][Web Board]

Description

给定一张无向图,求图中一个至少包含3个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称
为无向图的最小环问题。在本题中,你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。若无解,输
出"No solution."。图的节点数不超过100。

Input

Output

Sample Input

5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20

Sample Output

1 3 5 2
d[i][j]在外层循环刚开始时表示1...k-1的最短路距离那么d[i][j]+a[i][k]+a[k][j]构成一个环,更新最小环即可
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;

const int maxn=300+10;
const int nil=0x3f3f3f3f;

int a[maxn][maxn],pos[maxn][maxn],d[maxn][maxn];
vector<int>path;
stack<int>s;

void getpath(int x,int y){
     if(pos[x][y]==-1) return ;
     getpath(x,pos[x][y]);
     path.push_back(pos[x][y]);
     getpath(pos[x][y],y);
}

int main(){
    int n,m,x,y,w;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++){
        for (int j=1;j<=n;j++){
            a[i][j]=d[i][j]=nil;
            pos[i][j]=-1;
        }
    }
    for (int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&w);
        d[x][y]=d[y][x]=a[x][y]=a[y][x]=min(a[x][y],w);
    }
    int ans=nil;
    for (int k=1;k<=n;k++){
        for (int i=1;i<k;i++)
            for (int j=i+1;j<k;j++)
                if(ans>(long long)d[i][j]+a[i][k]+a[k][j]){
                    ans=d[i][j]+a[i][k]+a[k][j];
                    path.clear();
                    path.push_back(i);
                    getpath(i,j);
                    path.push_back(j);
                    path.push_back(k);
                }
        for (int i=1;i<=n;i++){
            for (int 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(ans==nil) printf("No solution.");
    else {
        printf("%d",path[0]);
        for (int i=1;i<path.size();i++) printf(" %d",path[i]);
    }
return 0;
}

 

 






以上是关于麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢的主要内容,如果未能解决你的问题,请参考以下文章

UOJ #276 无向图最小环

UOJ 276无向图最小环

floyd求最小环

POJ 1734 无向图最小环/有向图最小环

最小环

最小环