山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

vijosP1046 观光旅游(最小环)

vijosP1046 观光旅游

 

链接:https://vijos.org/p/1046

 

【思路】

  Floyd求解最小环。

 

【代码】 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int maxn = 100+10;
 5 const int INF=1e8;
 6 int f[maxn][maxn],dist[maxn][maxn];
 7 int n,m,min_loop;
 8 
 9 void Floyd() 
10 {
11     min_loop=INF;
12     for(int k=1;k<=n;k++) 
13     {
14         for(int i=1;i<k;i++)
15            for(int j=i+1;j<k;j++)
16               if(f[i][j]+dist[i][k]+dist[k][j]<min_loop)
17                  min_loop=f[i][j]+dist[i][k]+dist[k][j];
18         
19         for(int i=1;i<=n;i++)
20            for(int j=1;j<=n;j++)
21               if(f[i][k]<INF && f[k][j]<INF)
22                  f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
23     }
24 }
25 
26 int main() {
27     ios::sync_with_stdio(false);
28     while(cin>>n>>m)
29     {
30         for(int i=1;i<=n;i++)
31          {
32            f[i][i]=dist[i][i]=0;
33            for(int j=i+1;j<=n;j++) 
34               f[i][j]=f[j][i]=dist[i][j]=dist[j][i]=INF;
35         }
36         int u,v,w;
37         for(int i=0;i<m;i++) {
38             cin>>u>>v>>w;
39             dist[u][v]=dist[v][u]=f[u][v]=f[v][u]=w;
40         }
41         Floyd();
42         if(min_loop==INF) cout<<"No solution.\n";
43         else cout<<min_loop<<"\n";
44     }
45     return 0;
46 }
View Code

 

【参考代码及原理】

 

  1 /*
  2  *算法引入:
  3  *求一个图G中的最小环路的朴素算法为:每次找到一条边,删除了求这两点之间的最短路径;
  4  *若能求出,则这条最短路径与原来的边构成一个环,不过时间复杂度略高;
  5  *
  6  *算法思想;
  7  *Floyd算法是按照顶点的编号增加的顺序更新最短路径的;
  8  *如果存在最小环,则会在这个环中的点编号最大的那个点u更新最短路径之前发现这个环;
  9  *即当点u被拿来更新i到j的最短路径的时候,可以发现这个闭合环路;
 10  *发现的方法是,更新最短路径前,遍历i,j点对,一定会发现某对i到j的最短路径长度:
 11  *dist[i][j]+map[j][u]+map[u][i]!=INF,这时s的i和j是当前环中挨着点u的两个点;
 12  *因为在之前的最短路径更新过程中,u没有参与更新,所以dist[i][j]所表示的路径中不会有点u,即一定为一个环;
 13  *
 14  *如果在每个新的点拿来更新最短路径之前遍历i和j验证上面的式子,虽然不能遍历到所有的环;
 15  *但是由于dist[i][j]是i到j点的最短路径m所以肯定可以遍历到最小的环;
 16  *
 17  *如果有负权环,则该算法失效,因为包含负环的图上,dist[i][j]已经不能保证i到j的路径上不会经过同一个点多次了;
 18  *
 19  *算法测试:
 20  *PKU1734(Sightseeing trip)
 21  */
 22 
 23 #include<iostream>
 24 #include<cstring>
 25 #include<cstdlib>
 26 #include<queue>
 27 #include<cstdio>
 28 #include<climits>
 29 #include<algorithm>
 30 using namespace std;
 31 
 32 const int N=111;
 33 const int INF=0xffffff;
 34 
 35 int min_loop;
 36 int num;
 37 int map[N][N],dist[N][N],pre[N][N];
 38 int path[N];
 39 int n,m;
 40 
 41 void dfs(int i,int j)
 42 {
 43     int k=pre[i][j];
 44     if(k==0)
 45     {
 46         path[num++]=j;
 47         return;
 48     }
 49     dfs(i,k);
 50     dfs(k,j);
 51 }
 52 
 53 void Floyd()
 54 {
 55     min_loop=INF;
 56     memset(pre,0,sizeof(pre));
 57     for(int k=1; k<=n; k++)
 58     {
 59         for(int i=1; i<k; i++)   //i<k
 60         {
 61             for(int j=i+1; j<k; j++)    //j<k 
 62             {
 63                 if(dist[i][j]+map[i][k]+map[k][j]<min_loop)
 64                 {
 65                     min_loop=dist[i][j]+map[i][k]+map[k][j];
 66                     num=0;
 67                     path[num++]=i;
 68                     dfs(i,j);
 69                     path[num++]=k;
 70                 }
 71             }
 72         }
 73 
 74         for(int i=1; i<=n; i++)
 75         {
 76             for(int j=1; j<=n; j++)
 77             {
 78                 if(dist[i][k]+dist[k][j]<dist[i][j])
 79                 {
 80                     dist[i][j]=dist[i][k]+dist[k][j];
 81                     pre[i][j]=k;
 82                 }
 83             }
 84         }
 85     }
 86 }
 87 
 88 int main()
 89 {
 90    // freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
 91     while(~scanf("%d%d",&n,&m))
 92     {
 93         for(int i=1; i<=n; i++)
 94         {
 95             for(int j=i+1; j<=n; j++)
 96                 map[i][j]=map[j][i]=dist[i][j]=dist[j][i]=INF;
 97             map[i][i]=dist[i][i]=0;
 98         }
 99         for(int i=0; i<m; i++)
100         {
101             int u,v,w;
102             scanf("%d%d%d",&u,&v,&w);
103             if(w<map[u][v])
104             {
105                 map[u][v]=map[v][u]=w;
106                 dist[u][v]=dist[v][u]=w;
107             }
108         }
109         Floyd();
110         if(min_loop==INF)
111             puts("No solution.");
112         else
113         {
114             for(int i=0; i<num-1; i++)
115                 printf("%d ",path[i]);
116             printf("%d\n",path[num-1]);
117         }
118     }
119     return 0;
120 }

 

  转载地址:http://blog.csdn.net/jarily/article/details/8872487

 

posted on 2015-10-26 14:58  hahalidaxin  阅读(359)  评论(0编辑  收藏  举报