zoukankan      html  css  js  c++  java
  • [Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)

    题目链接:

    https://codeforces.com/contest/1051/problem/F

    题目大意:

    给出一张$n$个点,$m$条边的带权无向图,多次询问,每次给出$u,v$,要求输出$u$到$v$的最短距离

    $1<=n<=m<=10^5,m-n<=20$

    题解:

    显然我们要从$m-n<=20$入手,发现这张图非常的稀疏,所以按照套路我们先随便搞一棵生成树(和kruskal的步骤差不多只是去掉了排序)。

    当询问两个点$u,v$的最短距离时我们先只考虑树上的点,显然我们可以预处理出到根节点的距离$O(qlogn)$的搞。

    然后考虑非树边,我们称非树边的端点为特殊点,特殊点的个数小于等于40,显然不在树上的最短路径肯定至少经过一个特殊点,所以我们对每个特殊点跑一次dijkstra,然后每次再枚举一下特殊点更新答案即可

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<set>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int N=2e5+15;
    const ll inf=1e17;
    int n,m,tot,k;
    int u[N],v[N],tmp[N],fa[N][25],f[N],head[N],d[N];
    ll dd[50][N],dep[N],w[N];
    struct EDGE
    {
        int to,nxt;ll w;
    }edge[N<<1];
    struct NODE
    {
        int to;ll w;
    };
    vector <NODE> g[N];
    set <int> p;
    struct node
    {
        int now;ll dis;
    };
    bool operator < (node x,node y) {return x.dis>y.dis;}
    inline ll read()
    {
        char ch=getchar();
        ll s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    int find(int x)
    {
        if (x!=f[x]) f[x]=find(f[x]);
        return f[x];
    }
    void add(int x,int y,ll w)
    {
        edge[++tot]=(EDGE){y,head[x],w};
        head[x]=tot;
    }
    void dij(int s)
    {
        ++k;
        for (int i=1;i<=n;i++) dd[k][i]=inf;
        dd[k][s]=0;
        priority_queue <node> q; 
        q.push((node){s,0});
        while (!q.empty())
        {
            node e=q.top();q.pop();
            int now=e.now;
            if (dd[k][now]!=e.dis) continue;
            for (int i=0;i<g[now].size();i++)
            {
                int y=g[now][i].to;
                if (dd[k][y]>dd[k][now]+g[now][i].w)
                {
                    dd[k][y]=dd[k][now]+g[now][i].w;
                    q.push((node){y,dd[k][y]});
                }
            }
        }
    }
    void dfs(int x,int pre)
    {
        for (int i=1;i<=24;i++) 
        {
            if (d[x]<(1<<i)) break;
            fa[x][i]=fa[fa[x][i-1]][i-1];
        }
        for (int i=head[x];i;i=edge[i].nxt)
        {
            int y=edge[i].to;
            if (y==pre) continue;
            fa[y][0]=x;
            dep[y]=dep[x]+edge[i].w;
            d[y]=d[x]+1;
            dfs(y,x);
        }
    }
    int lca(int x,int y)
    {
        if (d[x]<d[y]) swap(x,y);
        for (int i=24;i>=0;i--) if (d[fa[x][i]]>=d[y]) x=fa[x][i];
        if (x==y) return x;
        for (int i=24;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    int main()
    {    
        n=read();m=read();
        for (int i=1;i<=m;i++)
        {
            u[i]=read();v[i]=read();w[i]=read();
            g[u[i]].push_back((NODE){v[i],w[i]});
            g[v[i]].push_back((NODE){u[i],w[i]});
        }
        for (int i=1;i<=n;i++) f[i]=i;
        for (int i=1;i<=m;i++)
        {
            int U=find(u[i]),V=find(v[i]);
            if (U!=V)
            {
                f[U]=V;
                tmp[i]=1;
            }
        }
        for (int i=1;i<=m;i++)
        {
            if (tmp[i]) {add(u[i],v[i],w[i]);add(v[i],u[i],w[i]);}//printf("qq%d %d
    ",u[i],v[i]);
            else p.insert(u[i]),p.insert(v[i]);
        }
        for (set<int>::iterator it=p.begin();it!=p.end();it++) dij((*it));
        d[0]=-1;dfs(1,-1);
        //printf("dd%d
    ",fa[2][0]);
        int q=read();
        while (q--)
        {
            int x=read(),y=read();
            int LCA=lca(x,y);
            //printf("LL%d
    ",LCA);
            ll mi=dep[x]+dep[y]-2*dep[LCA];
            //printf("LL%lld
    ",mi);
            for (int i=1;i<=k;i++)
            {
                mi=min(mi,dd[i][x]+dd[i][y]);
            }
            printf("%lld
    ",mi);
        }
        return 0;
    }
  • 相关阅读:
    postman一健导入swagger api所有接口
    pycharm 通过project interpreter国内镜像源设置
    Linux常用软件tree,autojump,lrzsz安装
    文献下载好用网站推荐
    SCIP,Clp,Gurobi和Cplex安装
    Linux下SuperLU安装
    【微服务理论】康威定律
    项目实战:动态系统的设计(类似朋友圈)
    认知提升:工作和薪资
    博客园美化 Cnblogs-Theme-SimpleMemory
  • 原文地址:https://www.cnblogs.com/xxzh/p/9765154.html
Copyright © 2011-2022 走看看