题解Luogu CF1051F The Shortest Statement

Posted yzhang-rp-inf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解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;
}

以上是关于题解Luogu CF1051F The Shortest Statement的主要内容,如果未能解决你的问题,请参考以下文章

CF1051F The Shortest Statement

CF1051F The Shortest Statement

CF1051F The Shortest Statement

CF1051F The Shortest Statement

CF 1051F The Shortest Statement (最短路)

[Codeforces 1051F] The Shortest Statement 解题报告(树+最短路)