zoukankan      html  css  js  c++  java
  • BZOJ 2125 最短路

    边仙人掌。环上的点全部连向这个环上深度最小的点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxv 500050
    #define maxe 1000050
    #define inf 0x7f7f7f7f7f7f7f7fLL
    using namespace std;
    int n,m,qt,x[maxe],y[maxe],w[maxe],u,v,dep[maxv],anc[maxv][21],g[maxv],deps[maxv];
    int id[maxv],bel[maxv],len[maxv],tot=0,pre[maxv],st[maxv],top=0,nume=1,prew[maxv],kr=0;
    long long dis[maxv];
    bool vis[maxv];
    struct edge
    {
        int v,w,nxt;
    }e[maxe];
    struct data
    {
        int a,b;
        data (int a,int b):a(a),b(b) {}
        data () {}
    };
    queue <int> q;
    int read()
    {
        char ch;int data=0;
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9')
        {
            data=data*10+ch-'0';
            ch=getchar();
        }
        return data;
    }
    void addedge(int u,int v,int w)
    {
        e[++nume].v=v;e[nume].w=w;e[nume].nxt=g[u];g[u]=nume;
        e[++nume].v=u;e[nume].w=w;e[nume].nxt=g[v];g[v]=nume;
    }
    void spfa()
    {
        for (int i=2;i<=n;i++) dis[i]=inf;dis[1]=0;
        q.push(1);vis[1]=true;int war=0;
        while (!q.empty())
        {
            war++;
            int head=q.front();q.pop();
            for (int i=g[head];i;i=e[i].nxt)
            {
                int v=e[i].v;
                if (dis[v]>dis[head]+e[i].w)
                {
                    dis[v]=dis[head]+e[i].w;dep[v]=dep[head]+1;
                    pre[v]=head;prew[v]=e[i].w;
                    if (!vis[v]) {vis[v]=true;q.push(v);}
                }
            }
            vis[head]=false;
        }
    }
    void dfs(int x)
    {
        vis[x]=true;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (anc[x][0]==v || vis[v]) continue;
            deps[v]=deps[x]+1;dfs(v);
        }
    }
    void build()
    {
        nume=1;memset(g,0,sizeof(g));memset(vis,false,sizeof(vis));
        for (int i=1;i<=m;i++)
        {
            if (pre[x[i]]==y[i] || pre[y[i]]==x[i]) continue;
            top=0;tot++;
            u=x[i];v=y[i];
            if (dep[u]<dep[v]) swap(u,v);len[tot]=w[i];
            while (dep[u]>dep[v]) {st[++top]=u;bel[u]=1;len[tot]+=prew[u];u=pre[u];}
            while (u!=v) {st[++top]=u;st[++top]=v;bel[u]=1;bel[v]=2;len[tot]+=prew[u]+prew[v];u=pre[u];v=pre[v];}
            for (int j=1;j<=top;j++) {anc[st[j]][0]=u;addedge(st[j],u,dis[st[j]]-dis[u]);id[st[j]]=tot;}
        }
        for (int i=1;i<=m;i++)
        {
            u=x[i];v=y[i];
            if (dep[u]>dep[v]) swap(u,v);
            if (id[u]==id[v] && id[u]) continue;
            if (id[v] && !id[u]) continue;
            anc[v][0]=u;addedge(u,v,w[i]);
        }
        dfs(1);
        for (int e=1;e<=20;e++)
            for (int i=1;i<=n;i++)
                anc[i][e]=anc[anc[i][e-1]][e-1];
    }
    data lca(int x,int y)
    {
        int rx=x,ry=y;
        for (int e=20;e>=0;e--)
        {
            if (deps[anc[x][e]]>=deps[y] && anc[x][e])
                x=anc[x][e];
        }
        if (x==y) return data(x,0);
        for (int e=20;e>=0;e--)
        {
            if (anc[x][e]!=anc[y][e])
            {
                x=anc[x][e];
                y=anc[y][e];
            }
        }
        return data(x,y);
    }
    long long get_ans(int x,int y)
    {
        if (dep[x]>dep[y]) swap(x,y);long long rr,dx,dy;
        dx=dis[x]-dis[anc[x][0]];dy=dis[y]-dis[anc[y][0]];
        if (bel[x]==bel[y]) rr=min(dy-dx,len[id[x]]+dx-dy);
        else rr=min(dx+dy,len[id[x]]-dx-dy);
        return rr;
    }
    int main()
    {
        n=read();m=read();qt=read();
        for (int i=1;i<=m;i++)
        {
            x[i]=read();y[i]=read();w[i]=read();
            addedge(x[i],y[i],w[i]);
        }
        spfa();
        build();
        for (int i=1;i<=qt;i++)
        {
            u=read();v=read();if (deps[u]<deps[v]) swap(u,v);
            data ret=lca(u,v);
            if (!ret.b) printf("%lld
    ",dis[u]-dis[ret.a]);
            else
            {
                if (id[ret.a]==id[ret.b] && id[ret.a]) printf("%lld
    ",dis[u]+dis[v]-dis[ret.a]-dis[ret.b]+get_ans(ret.a,ret.b));
                else printf("%lld
    ",dis[u]+dis[v]-2*dis[anc[ret.a][0]]);   
            }
        }
        return 0;
    }
    
  • 相关阅读:
    MPS和MRP之间有什么样的关系呢
    java中静态代码块详解
    SQL server 分组后每组取出任意一行
    人是否能成功,其实可能很早就能看出来
    国内外产品经理的区别
    Yarn 和 NPM 国内快速镜像(淘宝镜像)
    vue-cli 使用less 遇到的问题 || vue-cli 使用less
    布隆过滤器
    PHP性能优化
    Redis-高并发代言词,为什么做分布式要Redis?
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/7773086.html
Copyright © 2011-2022 走看看