题目链接:旅行社的烦恼
题意是求无向图的最小环,如果有的话,输出个数,并且输出权值。
刚刚补了一发floyd 动态规划原理,用了滑动数组的思想。所以,这个题就是floyd思想的变形。在k从1到n的过程中更新到k时,mindis数组中保存的是只经过1~k-1序号的点时,任意两个之间的最短路权值,这时候,选择点k作为环的起点即终点,在[1, k)之间选择两个点i, j 得到一个环,环的权值即为mindis[i][j] + dis[i][k] + dis[j][k]。这样遍历得到的是就是所有的环,且环内不出现重复的点。环也不会重复。好巧妙~~献上我的膝盖...
附代码:
#include <stdio.h> #include <string.h> #include <iostream> #define inf 100000000 using namespace std; int dis[110][110]; int mindis[110][110]; int main() { int t; cin >> t; while(t--) { int n, m; cin >> n >> m; for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) { dis[i][j] = inf; } } for (int i=0; i<m; ++i) { int x, y, w; cin >> x >> y >> w; if (dis[x][y] > w) { dis[x][y] = w; dis[y][x] = w; } } for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) { mindis[i][j] = dis[i][j]; } } int ansdis = inf, anscnt = 0; for (int k=1; k<=n; ++k) { for (int i=1; i<k; ++i) { for (int j=i+1; j<k; ++j) { if (ansdis > dis[i][k] + dis[j][k] + mindis[i][j]) { ansdis = dis[i][k] + dis[j][k] + mindis[i][j]; anscnt = 1; } else if (ansdis == dis[i][k] + dis[j][k] + mindis[i][j]) { anscnt++; } } } for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) { mindis[i][j] = min(mindis[i][j], mindis[i][k] + mindis[j][k]); // 感觉最后一个mindis[j][k] 如果换成mindis[k][j]的话应该WA的,然而并没有。好奇怪... } } } if (anscnt == 0) { cout << "-1 "; } else cout << ansdis << " " << anscnt << endl; } return 0; }
注释处...mindis[j][k]应该是不等于mindis[k][j]的..不解...................