• CF1051F The Shortest Statement


    CF1051F The Shortest Statement

    题目描述

    You are given a weighed undirected connected graph, consisting of n n vertices and m m edges.

    You should answer q q queries, the (i) -th query is to find the shortest distance between vertices (u_i) and (v_i).

    输入输出格式

    输入格式:

    The first line contains two integers (n) and (m) ((1 le n, m le 10^5, m - n le 20)) — the number of vertices and edges in the graph.

    Next (m) lines contain the edges: the (i) -th edge is a triple of integers (v_i, u_i, d_i) ((1 le u_i, v_i le n, 1 le d_i le 10^9, u_i eq v_i)).

    This triple means that there is an edge between vertices (u_i) and (v_i) of weight (d_i) . It is guaranteed that graph contains no self-loops and multiple edges.

    The next line contains a single integer (q~(1 le q le 10^5)) — the number of queries.

    Each of the next (q) lines contains two integers (u_i) and (v_i~(1 le u_i, v_i le n)) — descriptions of the queries.

    Pay attention to the restriction (m - n ~ le ~ 20).

    输出格式:

    Print (q) lines.

    The (i) -th line should contain the answer to the (i) -th query — the shortest distance between vertices (u_i) and (v_i).


    不错的题目

    发现Pay attention...,所以肯定有用了(一般看数据范围这么奇怪也会想到吧

    思路:先跑一颗生成树,然后把不在生成树的边的端点拿出来,以每个端点跑最短路。询问直接枚举经过哪个端点或者直接是树上路径


    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define ll long long
    const int N=1e5+10;
    int n,m,Q;
    int head[N],to[N<<1],Next[N<<1],cnt=1;
    ll edge[N<<1],dis[N];
    void add(int u,int v,ll w)
    {
        to[++cnt]=v,Next[cnt]=head[u],edge[cnt]=w,head[u]=cnt;
    }
    int is[N<<1],used[N],f[N][21],dep[N];
    void dfs(int now)
    {
        for(int i=1;f[now][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
        used[now]=1;
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(!used[v])
            {
                is[i]=is[i^1]=1;
                dis[v]=dis[now]+edge[i];
                f[v][0]=now;
                dep[v]=dep[now]+1;
                dfs(v);
            }
        }
    }
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=20;~i;i--)
            if(dep[f[x][i]]>=dep[y])
                x=f[x][i];
        if(x==y) return x;
        for(int i=20;~i;i--)
            if(f[x][i]!=f[y][i])
                x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    int point[100],tot;
    #define P pair <ll,int>
    priority_queue <P,vector <P>,greater <P> > q;
    ll diss[100][N];
    void dijs()
    {
        memset(diss,0x3f,sizeof(diss));
        for(int i=1;i<=tot;i++)
        {
            int u=point[i];
            diss[i][u]=0;
            q.push(make_pair(0,u));
            memset(used,0,sizeof(used));
            while(!q.empty())
            {
                int now=q.top().second;
                q.pop();
                if(used[now]) continue;
                used[now]=1;
                for(int j=head[now];j;j=Next[j])
                {
                    int v=to[j];
                    if(diss[i][v]>diss[i][now]+edge[j])
                    {
                        diss[i][v]=diss[i][now]+edge[j];
                        q.push(make_pair(diss[i][v],v));
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        ll w;
        for(int u,v,i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,w),add(v,u,w);
        }
        dfs(1);
        for(int u=1;u<=n;u++)
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i];
                if(!is[i]) point[++tot]=u,point[++tot]=v;
            }
        sort(point+1,point+1+tot);
        tot=unique(point+1,point+1+tot)-point-1;
        dijs();
        scanf("%d",&Q);
        for(int u,v,i=1;i<=Q;i++)
        {
            scanf("%d%d",&u,&v);
            int lca=LCA(u,v);
            ll ans=dis[u]+dis[v]-dis[lca]*2;
            for(int j=1;j<=tot;j++)
                ans=min(ans,diss[j][u]+diss[j][v]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    

    2018.10.10

  • 相关阅读:
    python--模块与包
    内置函数 的总结
    迭代器 生成器 列表推导式 生成器表达式的一些总结
    函数的有用信息 带参数的装饰器 多个装饰器装饰一个函数
    函数名的应用(第一对象) 闭包 装饰器
    动态参数 名称空间 作用域 作用域链 加载顺序 函数的嵌套 global nonlocal 等的用法总结
    函数的初识 函数的返回值 参数
    文件操作 常用操作方法 文件的修改
    遍历字典的集中方法 集合的作用 以及增删查的方法
    计算机硬件的小知识
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9764256.html
Copyright © 2020-2023  润新知