POJ 1734 Sightseeing trip(最小环-floyd)
2016-03-15 11:26
344 查看
Description
给出一张n个点的无向图,每条边有边权,求最小环,顺次输出最小环上的点
Input
第一行两个整数n和m表示点数和边数,之后m行每行三个整数a,b,c表示a点和b点之间有一条边权为c的边(n<=100,m<=10000)
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
Solution
Floyd求最小环,在Floyd求最短路的过程中是按点的编号从小到大更细最短路径的,也就是说如果存在一个环,那么会在更新这个环中编号最大的那个点u的最短路径之前就发现这个环,也就是说u被拿来更新i到j的最短路径时会发现这个环,即dis[i][j]+map[j][u]+map[u][i]!=INF(dis[i][j]是i到j的最短路径,map[i][j]是原图中i到j的边权),此时i和j是环中与u相邻的两个点,因为在此前u不会参与更新,也就是说i到j的路径中不可能含有u,那么i->j->u->i即为一个环,虽然这样无法遍历所有的环,但是由于dis[i][j]记录的是i到j的最短路径,而同在一个环上的两个点,其最短路径一定在这个环中,所以这样在更新过程中更新环的最小长度最后就可以得到最小环,注意此题要记录路径,所以要在普通的floyd基础上加上数组pre[i][j]记录i到j的路径上j点前一个点的编号,这样就可以记录下来i到j的路径,那么在更新最小环长度的时候就可以根据pre数组记录最小环上的点
Code
给出一张n个点的无向图,每条边有边权,求最小环,顺次输出最小环上的点
Input
第一行两个整数n和m表示点数和边数,之后m行每行三个整数a,b,c表示a点和b点之间有一条边权为c的边(n<=100,m<=10000)
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
Solution
Floyd求最小环,在Floyd求最短路的过程中是按点的编号从小到大更细最短路径的,也就是说如果存在一个环,那么会在更新这个环中编号最大的那个点u的最短路径之前就发现这个环,也就是说u被拿来更新i到j的最短路径时会发现这个环,即dis[i][j]+map[j][u]+map[u][i]!=INF(dis[i][j]是i到j的最短路径,map[i][j]是原图中i到j的边权),此时i和j是环中与u相邻的两个点,因为在此前u不会参与更新,也就是说i到j的路径中不可能含有u,那么i->j->u->i即为一个环,虽然这样无法遍历所有的环,但是由于dis[i][j]记录的是i到j的最短路径,而同在一个环上的两个点,其最短路径一定在这个环中,所以这样在更新过程中更新环的最小长度最后就可以得到最小环,注意此题要记录路径,所以要在普通的floyd基础上加上数组pre[i][j]记录i到j的路径上j点前一个点的编号,这样就可以记录下来i到j的路径,那么在更新最小环长度的时候就可以根据pre数组记录最小环上的点
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 111 #define INF 0x3f3f3f3f typedef long long ll; int n,m,map[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn],path[maxn],res; int Min_Circle() { int ans=INF; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=map[i][j],pre[i][j]=i; for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&dis[i][j]!=INF&&map[j][k]!=INF&&map[k][i]!=INF&&ans>dis[i][j]+map[j][k]+map[k][i]) { ans=dis[i][j]+map[j][k]+map[k][i]; res=0; int t=j; while(t!=i) { path[res++]=t; t=pre[i][t]; } path[res++]=i,path[res++]=k; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis[i][k]!=INF&&dis[k][j]!=INF&&dis[i][j]>dis[i][k]+dis[k][j]) { dis[i][j]=dis[i][k]+dis[k][j]; pre[i][j]=pre[k][j]; } } return ans; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=dis[i][j]=INF; while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); map[a][b]=map[b][a]=min(map[a][b],c); } int ans=Min_Circle(); if(ans==INF)printf("No solution.\n"); else for(int i=0;i<res;i++) printf("%d%c",path[i],i==res-1?'\n':' '); } return 0; }
相关文章推荐
- Lua中的string库(字符串函数库)总结
- xpath学习积累
- 安卓开发-Activity中finish() onDestroy() 和System.exit()的区别(转)
- [转][译]关于CSS中的float和position和z-index
- Python的净值数据接口调用示例分享
- 让浏览器变身代码编辑器
- Struts2 注解零配置方法(convention插件使用)
- hdu_2669 Romantic(扩展欧几里得)
- Jni中C++和Java的参数传递(转)
- 使用Gson解析json
- Linux命令之rm
- python 反射调用
- js实现图片预显示
- 斗战神 琵琶之怨获取攻略
- Python简单连接MongoDB数据库的方法
- MapReduce: Partition
- [数论][CODEVS 1497 取余运算]解题报告
- HBase调优之参数详解
- RTC系统【转】
- smarty8内置函数