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;
    }
  • 相关阅读:
    experss路由工作原理
    mongoose学习参考
    express+nodejs 个人博客
    HTML5-CSS3学习20150410(一)
    js学习20150420(七)
    js学习20150401(六)
    js学习20150401(五)
    js学习20150401(四)
    【荐】使用eval()、new Function()将JSON字符串转换为JSON对象
    HTML5 Canvas核心技术—图形、动画与游戏开发.pdf7
  • 原文地址:https://www.cnblogs.com/xxzh/p/9765154.html
Copyright © 2011-2022 走看看