POJ 2253(二分+并查集/最短路)

给出n个点,求起点1 终点2的所有路径中最长路径最小的一个
(就是说求
{从起点到终点路径中的
[任意相邻两点的距离]
的最大值}
的最小值)

思路:二分最大值,对每次二分,判定是否有从1到2的路径,达到精度后输出就行了

代码(我是用kuangbin板子直接套最短路):

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#ifdef Wang_Zhifeng
#define debug(x)  cout << #x << ": " << x << endl;
#endif
/*
* 使用优先队列优化 Dijkstra 算法
* 复杂度 O(ElogE)
* 注意对 vectorE[MAXN] 进行初始化后加边
*/
const int inf = 0x3f3f3f3f;
const int MAXN = 1000010;

struct qnode {
    int v;
    int c;

    qnode(int _v = 0, int _c = 0) : v(_v), c(_c) {}

    bool operator<(const qnode &r) const {
        return c > r.c;
    }
};

struct Edge {

    int v, cost;

    Edge(int _v = 0, int _cost = 0) : v(_v), cost(_cost) {}
};

vector E[MAXN];
bool vis[MAXN];
int dist[MAXN];

//点的编号从 1 开始
void Dijkstra(int n, int start) {
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= n; i++)dist[i] = inf;
    priority_queue que;
    while(!que.empty())que.pop();
    dist[start] = 0;
    que.push(qnode(start, 0));
    qnode tmp;
    while(!que.empty()) {
        tmp = que.top();
        que.pop();
        int u = tmp.v;
        if(vis[u])continue;
        vis[u] = true;
        for(int i = 0; i < E[u].size(); i++) {
            int v = E[tmp.v][i].v;
            int cost = E[u][i].cost;
            if(!vis[v] && dist[v] > dist[u]+cost) {
                dist[v] = dist[u]+cost;
                que.push(qnode(v, dist[v]));
            }
        }
    }
}

void addedge(int u, int v, int w) {
    E[u].push_back(Edge(v, w));
}

int n;
int tmp[500][2];

double dis(int i, int j) {
    return (tmp[i][0]-tmp[j][0])*(tmp[i][0]-tmp[j][0])+(tmp[i][1]-tmp[j][1])*(tmp[i][1]-tmp[j][1]);
}

bool solve(double lim) {
    for(int i = 1; i <= n; ++i) {
        E[i].clear();
    }
    for(int i = 1; i <= n; ++i) {
        for(int j = i+1; j <= n; ++j) {
            if(dis(i, j) <= lim) {
                addedge(i, j, 1);
                addedge(j, i, 1);
            }
        }
    }
    Dijkstra(n, 1);
    return dist[2]!=inf;
}

int main() {
#ifdef Wang_Zhifeng
//    freopen("in.txt", "r", stdin);
    setvbuf(stdout, NULL, _IOFBF, 1024);
//    std::ios::sync_with_stdio(false);
//    cin.tie(0);
#endif
    int cnt = 1;
    while(scanf("%d", &n)) {
        if(n==0)break;
        for(int i = 1; i <= n; ++i) scanf("%d%d", &tmp[i][0], &tmp[i][1]);
        double l = 0, r = 50000000, mid;
        while(r-l >= 0.000001) {
            mid = (l+r)/2;
            if(solve(mid))r = mid;
            else l = mid;
        }
        printf("Scenario #%d\n", cnt++);
        printf("Frog Distance = %.3lf\n\n", sqrt(mid));
    }
    return 0;
}

优化:对于这个题来说,并查集的速度会更快,不过既然没有卡最短路,那就不改了

注意:交的时候用cout或者对应他的编译器(%lf对应的是C++,G++是%f),最后是两个空行

你可能感兴趣的:(POJ 2253(二分+并查集/最短路))