poj1734 Sightseeing trip[最小环]

一个最小环裸题。最小环的两种求法dijkstra和Floyd直接参见这里我就是从这里学的,不想写了。

注意这里最重要的一个点是利用了Floyd的dp过程中路径上点不超过$k$这一性质,来枚举环上最大编号并枚举连边,这样另外枚举的两个点的最短路肯定不会经过和$k$连的边。

坑点:

  • 平常inf都开0x3f3f3f3f,这题没注意,在求环那里如果三个inf一加,就爆掉了。。所以要改小一点。这个问题值得重视。
  • Floyd正常输出路径应该就更新的时候记录中间点,最后直接递归输出。但是这里因为记录路径中$x$和$y$间的最短路必须是不经过当时的大于等于$k$的点的,所以最小环答案更新即记路径,不能到最后用Floyd转移数组输出路径。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define dbg(x) cerr << #x << " = " << x <<endl
 7 using namespace std;
 8 typedef long long ll;
 9 typedef double db;
10 typedef pair<int,int> pii;
11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
16 template<typename T>inline T read(T&x){
17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
19 }
20 const int N=100+5,INF=0x0f0f0f0f;
21 int mp[N][N],dis[N][N],g[N][N],h[N][N],n,m,ans=INF,pt1,pt2,pt3;
22 void print(int i,int j){
23     if(!h[i][j]){printf("%d ",i);return;}
24     print(i,h[i][j]);
25     print(h[i][j],j);
26 }
27 void path(int i,int j){
28     h[i][j]=g[i][j];
29     if(!g[i][j])return;
30     path(i,g[i][j]),path(g[i][j],j);
31 }
32 
33 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
34     memset(mp,0x0f,sizeof mp),memset(dis,0x0f,sizeof dis);
35     read(n),read(m);
36     for(register int i=1,x,y,z;i<=m;++i)read(x),read(y),read(z),dis[x][y]=dis[y][x]=mp[y][x]=mp[x][y]=_min(mp[x][y],z);
37     for(register int i=1;i<=n;++i)dis[i][i]=mp[i][i]=0;
38     for(register int k=1;k<=n;++k){
39         for(register int i=1;i<k;++i)
40             for(register int j=i+1;j<k;++j)
41                 if(MIN(ans,mp[i][k]+mp[j][k]+dis[i][j]))
42                     pt1=i,pt2=j,pt3=k,path(i,j);//dbg(i),dbg(j),dbg(k);
43         for(register int i=1;i<=n;++i)
44             for(register int j=1;j<=n;++j)
45                 if(MIN(dis[i][j],dis[i][k]+dis[k][j]))
46                     g[i][j]=k;
47     }
48     if(ans<INF)print(pt1,pt2),printf("%d %d\n",pt2,pt3);
49     else puts("No solution.");
50     return 0;
51 }
View Code
posted @ 2019-09-28 20:26  Ametsuji_akiya  阅读(166)  评论(0编辑  收藏  举报