BZOJ 4239 巴士走读

来源:互联网 发布:网络转换器联通转电信 编辑:程序博客网 时间:2024/04/27 22:34

最短路

和正解的做法不一样,不过都是 O((q+n)logm)的。

我的做法:也是最短路。把巴士看成点,并拆成入点和出点,边权为y-x(走它的意义是坐了这个巴士)。对于每一个原图的点u,把所有从这里出去的巴士按x排序,x小的前一辆i-1的入点向后一辆i的入点连边,边权x[i]-x[i-1](走它的意义是去考虑坐i号巴士并消耗等车时间)。把每一辆进入u的巴士的出点连向所有离开u的巴士中x恰好大于它的y的巴士的入点,边权为出去的那辆巴士的y-进入的那辆巴士的x(走它的意义是换车的等车时间)。跑最短路之后在s的出边二分即可。

正解(贴PO爷原文,戳我查看原文):将二元组<站点,时间>看做一个点,那么点数是O(m)的 ,每辆巴士连一条边,每个点向下一个时间连边,然后将所有边反向 ,枚举终点站的每一个时间,加入队列广搜,得到最晚多久到达1号站点可以在这个时间到达终点站,然后对于每个询问去数组中二分即可

好气啊,不知道怎么的刚开始偏大数据拍WA了,后来代码没改重新拍又拍不WA了,交上去居然A了。。。呵呵呵呵

#include<cstdio>#include<vector>#include<cstring>#include<algorithm>#include<queue>#define N 600005using namespace std;namespace runzhe2000{    int read()    {        int r = 0; char c = getchar();        for(; c < '0' || c > '9'; c = getchar());        for(; c >='0' && c <='9'; c = getchar()) r=r*10+c-'0';        return r;    }    const int INF = 1<<28;    int n, m, last[N], ecnt, dis[N], T;    bool vis[N];    vector<int> in[N], out[N];    struct edge{int next, to, val;}e[N<<1];    struct Bus{int a, b, x, y;}bus[N];     struct item{int x, dis;};    bool operator < (item a, item b) {return a.dis > b.dis;}    bool cmp(int i1, int i2){return bus[i1].x < bus[i2].x;}    void addedge(int a, int b, int c){e[++ecnt] = (edge){last[a], b, c}; last[a] = ecnt;}    int pack(int i, int j){return i*2+j;}    void dijkstra()    {        memset(dis, 63, sizeof(dis));        priority_queue<item> q;        q.push((item){T, dis[T] = 0});        for(; !q.empty(); )        {            int x = q.top().x; q.pop();            if(vis[x])continue; vis[x] = 1;            for(int i = last[x]; i; i = e[i].next)            {                int y = e[i].to;                if(dis[x] + e[i].val <  dis[y])                     q.push((item){y, dis[y] = dis[x] + e[i].val});            }        }    }    void main()    {        n = read(), m = read();        for(int i = 1; i <= m; i++)        {            bus[i].a = read(), bus[i].b = read(), bus[i].x = read(), bus[i].y = read();            out[bus[i].a].push_back(i);            in[bus[i].b].push_back(i);            addedge(pack(i, 1), pack(i, 0), bus[i].y - bus[i].x);        }        for(int i = 1; i <= n; i++)            out[i].push_back(0);        bus[0].x = INF, bus[0].y = INF+INF;        for(int i = 1; i < n; i++)        {            sort(out[i].begin(), out[i].end(), cmp);            for(int j = 0; j < (int)in[i].size(); j++)            {                int u = in[i][j], l = 0, r = (int)out[i].size()-1;                for(; l < r; )                {                    int mid = (l+r)>>1;                    if(bus[out[i][mid]].x >= bus[u].y) r = mid;                    else l = mid+1;                }                addedge(pack(out[i][l], 0), pack(u, 1), bus[out[i][l]].x - bus[u].y);            }            for(int j = 1; j < (int)out[i].size(); j++)                 addedge(pack(out[i][j], 0), pack(out[i][j-1], 0), bus[out[i][j]].x - bus[out[i][j-1]].x);        }        T = pack(m+1,0);        for(int i = 0; i < (int)in[n].size(); i++)            addedge(T, pack(in[n][i], 1), 0);        dijkstra();        for(int i = 0; i < (int)out[1].size(); i++)            dis[pack(out[1][i], 0)] += bus[out[1][i]].x;        for(int Q =read(), t; Q--; )        {            t = read();            int l = 0, r = out[1].size() - 1;            for(; l < r; )            {                int mid = (l+r+1)>>1;                if(dis[pack(out[1][mid], 0)] <= t) l = mid;                else r = mid - 1;            }            if(dis[pack(out[1][l], 0)] <= t) printf("%d\n",bus[out[1][l]].x);            else puts("-1");        }    }}int main(){    runzhe2000::main();}
0 0