[BZOJ 3575] HNOI2014 道路堵塞

[BZOJ 3575] HNOI2014 道路堵塞_第1张图片

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

正解:注意到某个点被删掉之后,最短路依然是 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;
}

你可能感兴趣的:(数据结构,SPFA,bzoj)