HDU-4511 小明系列故事——女友的考验 floyd变种-标号递增最短路
题意:给定N个点,现在要求出从1号点到N号点的最短路。题目给的限制条件就是对于某条路径是不能够走的,但是可以选择某段路径走,另外就是所走的路径的标号必须是递增的。
分析:由于给定的是一些列的坐标点,这也就说原图其实是一个完全图。对于限制路径,其实只要限制的路径上点数超过2,那么明显可以选择从起点直接走到终点这条最短路来代替限制路径,因此该限制不起作用,而对于限制路径上点数为2的路径则需要标记一下不能够取。对于最终路径要求点坐标路径递增这一条件则直接在floyd处理的时候限制好i,j,k三者的关系即可。
#include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define sqr(x) ((x)*(x)) using namespace std; const int N = 55; const double eps = 1e-8; int n, m; int seq[N]; double mp[N][N]; int sign(const double &x) { return x < -eps ? -1 : x > eps ? 1 : 0; } struct Point { double x, y; bool operator == (const Point &t) const { return !sign(x-t.x) && !sign(y-t.y); } }p[N]; double dist(int a, int b) { return sqrt(sqr(p[a].x-p[b].x) + sqr(p[a].y-p[b].y)); } void floyd() { for (int k = 0; k < n; ++k) { for (int i = 0; i < k; ++i) { if (!sign(mp[i][k]+1)) continue; for (int j = k+1; j < n; ++j) { if (!sign(mp[k][j]+1)) continue; if (!sign(mp[i][j]+1) || sign(mp[i][j]-(mp[i][k]+mp[k][j])) > 0) { mp[i][j] = mp[i][k] + mp[k][j]; } } } } } int main() { while (scanf("%d %d", &n, &m), n|m) { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) mp[i][j] = 0; scanf("%lf %lf", &p[i].x, &p[i].y); } int t; for (int i = 0; i < m; ++i) { scanf("%d", &t); for (int j = 0; j < t; ++j) { scanf("%d", &seq[j]); } if (t == 2 && !(p[seq[0]-1] == p[seq[1]-1])) { mp[seq[0]-1][seq[1]-1] = mp[seq[1]-1][seq[0]-1]= -1; } } for (int i = 0; i < n; ++i) { for (int j = i+1; j < n; ++j) { if (sign(mp[i][j]+1)) mp[i][j] = mp[j][i] = dist(i, j); } } floyd(); if (sign(mp[0][n-1]+1)) printf("%.2f\n", mp[0][n-1]); else puts("Can not be reached!"); } return 0; }