最一般的方法就是二分高度,每次求一次最短路,看能不能求出来。 我的做法是先求一次最大生成树的最小边,就能得到高度,然后再求一次最短路。这样在高度比较大和数据比较大的时候,效率比二分那个方法要快很多。 poj 1797和这题比较类似, 只不过那题简单一些,只要求高度即可,不用求最短路。
我是用的是dijkstra求最短路和prim 求最大生成树。代码有点乱。
求最大生成树的关键点是只要连接到终点就终止,这样就能保证起点终点联通,并且高度最大。
/* ID: sdj22251 PROG: calfflac LANG: C++ */ #include <iostream> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cmath> #include <ctime> #define MAX 100000000 #define LOCA #define PI acos(-1.0) using namespace std; int dis[1001][1001],ans[1001], height[1001][1001], d[1001], dist[1001], n; bool is[1001], used[1001]; int main() { #ifdef LOCAL freopen("ride.in","r",stdin); freopen("ride.out","w",stdout); #endif int m, i, j, k, x, y, z, start, end, h, sth, cs= 0; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; if(cs != 0) printf("\n"); memset(is, false, sizeof(is)); for(i = 1; i <= n; i++) { for(j = 1; j <= n; j++) { dis[i][j] = MAX; height[i][j] = -1; } } for(i = 1; i <= m; i++) { scanf("%d%d%d%d", &x, &y, &z, &h); if(z == -1) z = 20000000; if(dis[x][y] > h || dis[y][x] > h) { dis[x][y] = h; dis[y][x] = h; } if(height[x][y] < z || height[y][x] < z) { height[x][y] = z; height[y][x] = z; } } scanf("%d%d%d", &start, &end, &sth); for(i = 1; i <= n; i++) { d[i] = height[start][i]; } //d[1] = 0; is[start] = true; int mx = MAX; int sum = 0; bool flag = false; int cnt = 0; for(i = 1; i < n; i++) { int mi = -1; int tmp; for(j = 1; j <= n; j++) { if(mi < d[j] && !is[j]) { mi = d[j]; tmp = j; } } if(mi == -1) break; if(mx > mi) mx = mi; if(tmp == end) { flag = true; break; } is[tmp] = true; for(j = 1; j <= n; j++) { if(!is[j] && d[j] < height[tmp][j]) { d[j] = height[tmp][j]; ans[j] = tmp; } } } if(!flag || mx == -1) {printf("Case %d:\n", ++cs); printf("cannot reach destination\n");} else { if(mx > sth) mx = sth; memset(used, 0, sizeof(used)); for(i = 1; i <= n; i++) dist[i] = MAX; dist[start] = 0; for(i = 1; i < n; i++) { int mi = MAX; int tmp = -1; for(j = 1; j <= n; j++) { if(dist[j] < mi && !used[j]) { tmp = j; mi = dist[j]; } } if(tmp != -1) {used[tmp] = 1; for(j = 1; j <= n; j++) { if(dist[j] > dist[tmp] + dis[tmp][j] && !used[j] && height[tmp][j] >= mx) { dist[j] = dist[tmp] + dis[tmp][j]; } } } } printf("Case %d:\n", ++cs); printf("maximum height = %d\nlength of shortest route = %d\n", mx, dist[end]); } } return 0; }