zoukankan      html  css  js  c++  java
  • [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;
        
    }
  • 相关阅读:
    HDU 5640 King's Cake
    HDU 5615 Jam's math problem
    HDU 5610 Baby Ming and Weight lifting
    WHU1604 Play Apple 简单博弈
    HDU 1551 Cable master 二分
    CodeForces659C Tanya and Toys map
    Codeforces 960E 树dp
    gym 101485E 二分匹配
    Codeforces 961E 树状数组,思维
    Codeforces Round #473 (Div. 2) D 数学,贪心 F 线性基,模板
  • 原文地址:https://www.cnblogs.com/evenbao/p/9734215.html
Copyright © 2011-2022 走看看