• [Codeforces 1051F] The Shortest Statement


    [题目链接]

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

    [算法]

            注意边数 - 点数 <= 20 , 我们不妨首先求出图的任意一棵生成树 , 不在生成树内的边最多有21条 , 这些边不同的端点最多有42个

            对这些点分别运行Dijkstra最短路

            回答“u至v的最短路"时 , 有如下两种情况 :

            1. 全部在生成树的边上 , 答案为生成树上两点距离

            2. 经过非树边 , 这样 , 我们只需枚举所有不在生成树内的边的端点 , 用其到u的最短路径 + 到v的最短路径更新答案即可

            时间复杂度 : O(NlogN)

    [代码]

             

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXK 50
    #define MAXLOG 20
    const int MAXN = 1e5 + 10;
    const long long inf = 1e18;
    
    int tot , n , m , q , k;
    int head[MAXN],f[MAXN],depth[MAXN],u[MAXN],v[MAXN],w[MAXN];
    int anc[MAXN][MAXLOG];
    bool mark[MAXN];
    long long ans[MAXN],sum[MAXN];
    long long dist[MAXK][MAXN];
    set< int > s;
    vector< pair<int,int> > G[MAXN];
    
    struct edge
    {
            int to , w , nxt;
    } e[MAXN << 2];
    struct query
    {
            int s , t , id;
    } a[MAXN];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u,int v,int w)
    {
            tot++;
            e[tot] = (edge){v,w,head[u]};
            head[u] = tot;
    }
    inline int get_root(int x)
    {
            if (f[x] == x) return x;
            else return f[x] = get_root(f[x]);
    }
    inline void dfs(int u,int fa)
    {
            for (int i = 1; i < MAXLOG; i++)
            {
                    if (depth[u] < (1 << i)) break;
                    anc[u][i] = anc[anc[u][i - 1]][i - 1];
            }
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to , w = e[i].w;        
                    if (v == fa) continue;
                    depth[v] = depth[u] + 1;
                    anc[v][0] = u;
                    sum[v] = sum[u] + w;
                    dfs(v,u);
            }        
    }
    inline int lca(int x,int y)
    {
            if (depth[x] > depth[y]) swap(x,y);
            for (int i = MAXLOG - 1; i >= 0; i--)
            {
                    if (depth[anc[y][i]] >= depth[x])
                            y = anc[y][i];
            }
            if (x == y) return x;
            for (int i = MAXLOG - 1; i >= 0; i--)
            {
                    if (anc[x][i] != anc[y][i])
                            x = anc[x][i] , y = anc[y][i];
            } 
            return anc[x][0];
    }
    
    inline long long dis(int x,int y)
    {
            return sum[x] + sum[y] - 2 * sum[lca(x,y)];
    }
    inline void dijkstra(int s,int k)
    {
            static bool visited[MAXN];
            priority_queue< pair<long long,int> > q;
            for (int i = 1; i <= n; i++) 
            {
                    dist[k][i] = inf;
                    visited[i] = false;
            }
            dist[k][s] = 0;
            q.push(make_pair(0,s));
            while (!q.empty())
            {
                    int cur = q.top().second;
                    q.pop();
                    if (visited[cur]) continue;
                    visited[cur] = true;
                    for (unsigned i = 0; i < G[cur].size(); i++)
                    {
                            int v = G[cur][i].first , w = G[cur][i].second;
                            if (dist[k][cur] + w < dist[k][v])
                            {
                                    dist[k][v] = dist[k][cur] + w;
                                    q.push(make_pair(-dist[k][v],v));
                            }
                    }
            }
    }
    int main()
    {
            
            read(n); read(m);
            for (int i = 1; i <= m; i++)
            {
                    read(u[i]); 
                    read(v[i]); 
                    read(w[i]);
                    G[u[i]].push_back(make_pair(v[i],w[i]));
                    G[v[i]].push_back(make_pair(u[i],w[i]));
            }
            for (int i = 1; i <= n; i++) f[i] = i;
            for (int i = 1; i <= m; i++)
            {
                    int x = get_root(u[i]) , y = get_root(v[i]);
                    if (x != y)
                    {
                            addedge(u[i],v[i],w[i]);
                            addedge(v[i],u[i],w[i]);
                            f[x] = y;
                            mark[i] = true;
                    } 
            }
            for (int i = 1; i <= m; i++)
            {
                    if (!mark[i])
                    {
                            s.insert(u[i]);
                            s.insert(v[i]);
                    }
            }
            dfs(1,-1);
            for (set< int > :: iterator it = s.begin(); it != s.end(); it++) dijkstra(*it,++k);
            read(q);
            while (q--)
            {
                    int u , v;
                    read(u); read(v);
                    long long ans = dis(u,v);
                    for (int i = 1; i <= k; i++) chkmin(ans,dist[i][u] + dist[i][v]);
                    printf("%I64d
    ",ans); 
            } 
            
            return 0;
        
    }
  • 相关阅读:
    第四次
    jsp
    2021.3.4
    第八次作业
    第七次作业
    第六周作业
    第五周作业
    第四周
    第四次jsp作业
    第二次作业
  • 原文地址:https://www.cnblogs.com/evenbao/p/9734215.html
Copyright © 2020-2023  润新知