URAL 2034 Caravans (最短路 + 二分)

来源:互联网 发布:新手特效制作软件 编辑:程序博客网 时间:2024/05/17 15:38

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=2034


题意:给你起点s和终点t,找出从起点到终点的最短路(可能不止一条),再给你一点r,让你找出r点到这些最短路上最近距离的最大值


思路:最大化最小值,可以联想到二分,可以先对r点跑一次最短路,算出r点到其他点的最短距离p[i],然后二分答案跑s,t之间的最短路,如果在松弛过程中发现某点v到r的距离不小于p[v],那么就不把v点加入松弛队列


#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <utility>#include <functional>#include <map>#include <string>using namespace std;const int maxn = 100010;const int mod = 1e9 + 7;const int inf = 0x3f3f3f3f;struct edge{    int to, nxt, w;} e[maxn * 2];int cnt;int n, m, mid;int head[maxn], vis[maxn], dis[maxn];int p[maxn];void init(){    cnt = mid = 0;    memset(head, -1, sizeof(head));    memset(vis, 0, sizeof(vis));}void add(int u, int v, int w){    e[cnt].w = w;    e[cnt].to = v;    e[cnt].nxt = head[u];    head[u] = cnt++;}int spfa(int s, int t){    memset(dis, inf, sizeof(dis));    memset(vis, 0, sizeof(vis));    deque <int> que;    que.push_back(s);    dis[s] = 0;    if (p[s] <= mid)        return inf;    while (!que.empty())    {        int u = que.front();        que.pop_front();        vis[u] = 0;        for (int i = head[u]; ~i; i = e[i].nxt)        {            int v = e[i].to;            if (p[v] <= mid) continue;            if (dis[v] > dis[u] + e[i].w)            {                dis[v] = dis[u] + e[i].w;                if (!vis[v])                {                    vis[v] = 1;                    if (!que.empty() && dis[v] <= dis[que.front()])                        que.push_front(v);                    else                        que.push_back(v);                }            }        }    }    return dis[t];}int main(){    while (~scanf("%d%d", &n, &m))    {        init();        for (int i = 0; i < m; i++)        {            int u, v;            scanf("%d%d", &u, &v);            add(u, v, 1);            add(v, u, 1);        }        int s, t, g;        scanf("%d%d%d", &s, &t, &g);        memset(p, inf, sizeof(p));        spfa(g, s);        for (int i = 1; i <= n; i++)            p[i] = dis[i];        //        for(int i = 1; i <= n; i++)        //            printf("%d ", p[i]);        //        printf("\n");        int ans = spfa(s, t);        // printf("%d\n", ans);        if (ans == inf)        {            puts("0");            continue;        }        int l = 0, r = n;        while (l < r)        {            mid = (l + r) / 2;            int res = spfa(s, t);            if (res == ans)                l = mid + 1;            else                r = mid;        }        printf("%d\n", l);    }    return 0;}




0 0
原创粉丝点击