BZOJ1576——[Usaco2009 Jan]安全路经Travel

来源:互联网 发布:手机照相优化算法 编辑:程序博客网 时间:2024/06/08 12:38

1、题意:给一无向图,图中点1到任意一点的最短路唯一,问把到每个点最短路上的最后一条边去掉,最短路是多少。
2、分析:这个题不是很会。。最短路树,真的是很高深哈哈。。从点1开始dijkstra,每一个的点是由另外的一个点松弛过来的,那么就连一条边,可以证明。。这是一棵树。(把无向的边分成两个有向边)对于一条不在树上的边,端点为u,v,考虑它能更新的范围,lca(u,v)v的这一段。不包括lca(u,v),可以画一个图思考一下。。
那么对于某一个点x的贡献为dis(u)+dis(v)+len(u,v)dis(x)
这里面dis(x)的固定的。那么也就是说对于这个链上都要与dis(u)+dis(v)+len(u,v)取最小值
可以使用树链剖分解决。但是一个更简单的方法:
按照dis(u)+dis(v)+len(u,v)对边排一个序,依次进行操作,对于这个链上的数都进行求值记录到答案中,由于从小到大排序过了,那么后面的边更新一定没有这个优,那么我们可以直接用并查集把这些点都连起来。
时间复杂度O(mlogm)

#include <map>#include <set>#include <cmath>#include <queue>#include <vector>#include <bitset>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define M 500010#define fi first#define se second#define LL long long#define MOD 1000000007#define inf 2147483647#define llinf 4000000000000000000ll#define For(i, x, y) for(int i = (x); i < (y); i ++)#define rep(i, x, y) for(int i = (x); i <= (y); i ++)#define drep(i, x, y) for(int i = (x); i >= (y); i --)inline int read(){    char ch=getchar();int x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline LL llread(){    char ch=getchar();LL x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}struct Edge{    int u, v, w, Next;} G[M];int head[M], tot;int n, m;inline void add(int u, int v, int w){    G[++ tot] = (Edge){u, v, w, head[u]};    head[u] = tot; }struct Node{    int d, u;    inline bool operator < (const Node& rhs) const{        return d > rhs.d;    }};priority_queue<Node> Q;int ft[M/4][20], ans[M], bian[M];int d[M], done[M], height[M] = {-1};inline void dijkstra(){    d[1] = 0; rep(i, 2, n) d[i] = inf;    rep(i, 1, n) done[i] = 0;    Q.push((Node){0, 1});    while(!Q.empty()){        Node x = Q.top(); Q.pop();        if(done[x.u]) continue;        done[x.u] = 1;        for(int i = head[x.u]; i != -1; i = G[i].Next){            Edge e = G[i];            if(d[e.v] > d[x.u] + e.w){                d[e.v] = d[x.u] + e.w;                Q.push((Node){d[e.v], e.v});                ft[e.v][0] = x.u;                height[e.v] = height[x.u] + 1;            }        }    }}inline void init(){    rep(i, 1, 18) rep(j, 1, n){        ft[j][i] = ft[ft[j][i - 1]][i - 1];    }}inline int lca(int x, int y){    if(height[x] < height[y]) swap(x, y);    int t = height[x] - height[y];    rep(i, 0, 18) if((1 << i) & t){        x = ft[x][i];    }    if(x == y) return x;    drep(i, 18, 0){        if(ft[x][i] != ft[y][i]){            x = ft[x][i];            y = ft[y][i];        }    }    return ft[x][0];}pair<int , pair<int , int> > T[M]; int fa[M];inline int find(int x){    return fa[x] == x ? x : fa[x] = find(fa[x]);}int fu[M], stt;int main(){    memset(head, -1, sizeof(head));    n = read(), m = read();    rep(i, 1, m){        int u = read(), v = read(), w = read();        add(u, v, w); add(v, u, w);    }     dijkstra(); init();    rep(i, 1, tot){        Edge e = G[i];        if(d[e.v] == d[e.u] + e.w){            bian[i] = 1;            /*if(i & 1) bian[i + 1] = 1;            else bian[i - 1] = 1;*/        }    }    //rep(i, 0, n) printf("%d\n", height[i]);    int st = 0;    rep(i, 1, tot) if(!bian[i]){        Edge e = G[i];        T[++ st].fi = d[e.u] + d[e.v] + e.w;        T[st].se.fi = e.v;        T[st].se.se = lca(e.u, e.v);        //printf("%d\n", lca(e.u, e.v));    }    //printf("%d\n", ft[12][0]);    sort(T + 1, T + st + 1);    rep(i, 1, n) fa[i] = i;    memset(ans, -1, sizeof(ans));    rep(i, 1, st){        stt = 0;        for(int x = T[i].se.fi; height[x] > height[T[i].se.se]; x = ft[find(x)][0]){            if(find(x) == x && ans[x] == -1){                ans[x] = T[i].fi - d[x];            }            fu[++ stt] = x;        }        For(j, 1, stt){            int pp = find(fu[j]), qq = find(fu[j + 1]);            if(pp != qq) fa[pp] = qq;        }    }    rep(i, 2, n) printf("%d\n", ans[i]);    return 0;}
1 0
原创粉丝点击