• 【题解】Luogu CF1051F The Shortest Statement


    原题传送门:CF1051F The Shortest Statement

    题目大意,给你一个稀疏图,q次查询,查询两点之间距离

    边数减点小于等于20

    这不是弱智题吗,23forever dalao又开始虐题

    作为蒟蒻的我只能在一旁出售烤绿鸟和main包,和大家一起吃西瓜

    仔细想想,这题的确是很弱智

    先随便找一个生成树,这样就能跑lca了

    剩下的几条边的端点跑一下SPFA堆优化dij,用于特判,SPFA已经死了

    查询先用lca算一下距离,再暴力枚举这40个端点到两点的距离值和(最多)

    就这样完了,没错

    程序中还有一些优化,看细节来体会(这题真的弱智)

    奉上蒟蒻的代码

    #pragma GCC optimize("O3")
    #include <bits/stdc++.h>
    #define N 300005
    #define Logn 19
    #define M 21
    #define inf 1e18
    #define ll long long
    using namespace std;
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline ll Min(register ll a,register ll b)
    {
        return a<b?a:b;
    }
    int n,m,q;
    struct edge{
        int to,next,w;
    }e[N<<1];
    int head[N],cnt=0;
    set< pair<int,int> >bad;
    int tin[N],tout[N],T;
    bool u[N];
    ll h[N],d[M<<1][N];
    int p[Logn][N];
    inline void add(register int u,register int v,register int w)
    {
        e[++cnt]=(edge){v,head[u],w};
        head[u]=cnt;
    }
    inline void dfs(register int v,register int pr)
    {
        tin[v]=T++;
        p[0][v]=pr;
        u[v]=true;
        for(register int i=1;i<Logn;++i)
            p[i][v]=p[i-1][p[i-1][v]];
        for(register int i=head[v];i;i=e[i].next)
            if(!u[e[i].to])
            {
                h[e[i].to]=h[v]+e[i].w;
                dfs(e[i].to,v);
                if(v<e[i].to)
                    bad.erase(make_pair(v,e[i].to));
                else
                    bad.erase(make_pair(e[i].to,v));
            }
        tout[v]=T;
    }
    inline bool isAncestor(register int a,register int b) 
    {
        return tin[a]<=tin[b]&&tout[a]>=tout[b];
    }
    inline int LCA(register int a,register int b)
    {
        if(isAncestor(a,b))
            return a;
        if(isAncestor(b,a))
            return b;
        for(register int i=Logn-1;i>=0;--i)
            if(!isAncestor(p[i][a],b))
                a=p[i][a];
        return p[0][a];
    }
    inline void dij(register int st,register ll d[N])
    {
        set<pair<ll,int> > q;
        for(register int i=0;i<n;++i)
            d[i]=inf;
        d[st]=0;
        q.insert(make_pair(d[st],st));
        while(!q.empty())
        {
            int v=q.begin()->second;
            q.erase(q.begin());
            for(register int i=head[v];i;i=e[i].next)
                if(d[e[i].to]>d[v]+e[i].w)
                {
                    q.erase(make_pair(d[e[i].to],e[i].to));
                    d[e[i].to]=d[v]+e[i].w;
                    q.insert(make_pair(d[e[i].to],e[i].to));
                }
        }
    }
    int main()
    {
        n=read(),m=read();
        for(register int i=1;i<=m;++i)
        {
            int u=read(),v=read(),w=read();
            --u,--v;
            add(u,v,w),add(v,u,w);
        }
        for(register int v=0;v<n;++v)
            for(register int i=head[v];i;i=e[i].next)
                if(v<e[i].to)
                    bad.insert(make_pair(v,e[i].to));
        dfs(0,0);
        int cpos=0;
        int siz=bad.size();
        while(!bad.empty())
            dij(bad.begin()->first,d[cpos++]),bad.erase(bad.begin());
        q=read();
        while(q--)
        {
            int u=read(),v=read();
            --u,--v;
            int lca=LCA(u,v);
            ll ans=h[u]+h[v]-2*h[lca];
            for(register int i=0;i<siz;++i)
                ans=Min(ans,d[i][u]+d[i][v]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    页面 笔记
    快速统计一个数二进制中1的个数
    [JAVA] String 拼接效率
    [JAVA] String常用方法
    [letcode] 832 Flipping an Image
    [java]冒泡排序
    SharedPreferences
    归并排序
    安全退出调用多个Activity的Application
    Activity生命周期
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/9741026.html
Copyright © 2020-2023  润新知