[BZOJ 3575] HNOI2014 道路堵塞

来源:互联网 发布:2016淘宝618报名 编辑:程序博客网 时间:2024/05/24 15:43

这里写图片描述

刚开始脑子一抽想到最短路树+树链剖分方向…感到不对去羞耻地查了查题解…

正解:注意到某个点被删掉之后,最短路依然是 pre(a) + dis(a, b) + suf(b) 的形式,pre 表示起点到a,suf表示从b到中点。 于是我们从起点到终点枚举最短路上每条边不选,维护每个点此时到起点dis值,因为在这个过程中dis单调,所以跑L次SPFA不会至于TLE…….[其实个人感觉挺玄学的]然后用堆维护一下答案…网上题解说是平衡树..差不多吧因为自己不太会用multiset啊哈哈哈哈哈哈哈

吐槽:跑到后面几页去了 TAT ,这份代码自我感觉是我换了码风之后最丑的一个了,我的写法可能不是标准正解…不过A了啊不管了

AC Code :

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;typedef long long LL;inline void read(int &x){x=0;char c;while((c=getchar())<'0'||c>'9');for(x=c-'0';(c=getchar())>='0'&&c<='9';x=x*10+c-'0');}const int inf = 0x3f3f3f3f;const int N = 100010 ;struct PQueue{    priority_queue<int, vector<int>, greater<int> > q, d;    void push(int x) { q.push(x); }    void remove(int x) { d.push(x); }    int top()     {        while (!d.empty() && q.top() == d.top()) q.pop(), d.pop();        return q.empty() ? -1 : q.top();    }}Q;struct edge{    int to, v, ban;    edge *n;}e[N * 2], *head[N], *cur = e + 1;inline void addEdge(int x, int y, int v){    cur->to = y, cur->v = v, cur->n = head[x], head[x] = cur++;}int D[N], B[N], n, m, L;int Stk[N], dis[N];void SPFA(int s, int b){    static int que[N], l, r;    static bool inq[N];    if (D[s] < inf) Q.remove(D[s] + B[s]);    l = r = 0, que[++r] = s;    while (l != r)    {        int u = que[++l];        inq[u] = 0;        if (l == N) l = 0;        for (edge *p = head[u]; p; p = p->n) if (!p->ban)        {            int to = p->to;            if (dis[to] > dis[u] + p->v)             {                dis[to] = dis[u] + p->v;                if (!inq[to])                {                    que[++r] = to, inq[to] = 1;                    if (r == N) r = 0;                }            }        }    }    for (int i = b + 1; i <= L + 1; ++i)     {        int u = Stk[i];        if (D[u] > dis[u])        {            if (D[u] < inf) Q.remove(D[u] + B[u]);            Q.push((D[u] = dis[u]) + B[u]);        }    }}int main(){    read(n), read(m), read(L);    for (int i = 0, x, y, v; i < m; ++i)    {        read(x), read(y), read(v);        addEdge(x, y, v);    }    for (int i = 1, u = 1, x; i <= L; ++i)    {        Stk[i] = u; read(x);        e[x].ban = 1;        D[e[x].to] = D[u] + e[x].v;        u = e[x].to;    }    for (int i = L, u = n; i; --i)    {        int x = Stk[i];        B[x] = B[u] + D[u] - D[x];        u = x;    }    memset(D, 0x3f, sizeof(D)); Stk[L + 1] = n;    memset(dis, 0x3f, sizeof(dis)), dis[1] = 0;    for (int i = 1; i <= L; ++i)     {        SPFA(Stk[i], i);        printf("%d\n", Q.top());        dis[Stk[i + 1]] = dis[Stk[i]] + B[Stk[i]] - B[Stk[i + 1]];    }    return 0;}
0 0
原创粉丝点击