您的位置:首页 > 其它

ural 1004 Sightseeing Trip 最小环

2012-04-30 10:03 211 查看
/*

题目:

寻找图中的最小环,输出路径。

分析:

可以通过枚举删除其中的一条边,看看能否从该边的一点走到另一点,若能并且该最短路的长度加上

删除的边的长度小于当前的最优解的话,更新路径与最优解。而打印路径可以通过数组来表示该点的

前一顶点,然后递归打印路径即可。最短路可以通过dijkstra算法求出。估计的时间复杂度为O(n^2*E)。

我交了一下,用时:1.328 内存:264 KB

*/

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

const int X = 105;

const int INF = 100000000;

int map[X][X],pre[X],ans[X],dis[X],n,m;

bool use[X];

int dijkstra(int s,int e){ //起点s,终点e

memset(use,false,sizeof(use));

memset(pre,0,sizeof(pre));

for(int i=1;i<=n;i++)

dis[i] = INF;

int MIN,k;

dis[s] = 0;

for(int i=1;i<=n;i++){

MIN = INF;

for(int j=1;j<=n;j++)

if(!use[j]&&dis[j]<MIN)

MIN = dis[k = j];

if(MIN==INF)

return INF;

use[k] = true;

for(int j=1;j<=n;j++)

if(!use[j]&&dis[j]>dis[k]+map[k][j]){

dis[j] = dis[k]+map[k][j];

pre[j] = k; //j的前一顶点为k

}

}

return dis[e];

}

void print(int pos){ //递归打印路径函数

if(!ans[pos])

return;

print(ans[pos]);

printf("%d ",ans[pos]);

}

int main(){

freopen("sum.in","r",stdin);

freopen("sum.out","w",stdout);

int x,y,z;

while(cin>>n,n!=-1){

for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

map[i][j] = INF; //题目的输入样例数据中有反向的边输入,并且是无向图

cin>>m;

for(int i=1;i<=m;i++){

scanf("%d%d%d",&x,&y,&z);

if(map[x][y]>z) //小于前面的长度时,更新

map[x][y] = map[y][x] = z;

}

int temp,ret,cnt = INF,pos = -1; //枚举所有的边

for(int j=1;j<=n;j++){

for(int i=1;i<=n;i++){

if(map[j][i]<INF){

temp = map[j][i];

map[j][i] = map[i][j] = INF;

ret = dijkstra(j,i)+temp;

map[j][i] = map[i][j] = temp;

if(ret<cnt){

pos = i;

for(int k=1;k<=n;k++)

ans[k] = pre[k];

cnt = ret;

}

}

}

}

if(pos==-1) //当pos==-1时表示图中没有环

printf("No solution.\n");

else{

print(pos);

cout<<pos<<endl;

}

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: