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 }