麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢相关的知识,希望对你有一定的参考价值。
RT
这个需要记录最小环上的点....
因此,在外层枚举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 MBSubmit: 15 Solved: 6
[Submit][Status][Web Board]
Description
给定一张无向图,求图中一个至少包含3个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称
为无向图的最小环问题。在本题中,你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。若无解,输
出"No solution."。图的节点数不超过100。
为无向图的最小环问题。在本题中,你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。若无解,输
出"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; }
以上是关于麻烦问下各路大牛 怎么求无向图中的最小环长度? 万分感谢的主要内容,如果未能解决你的问题,请参考以下文章