• [NOI 2018] 归程


    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=5415

    [算法]

             对于v到1的1条合法路径 , 我们将其分为两段考虑

             1. v -> u , 该路径上的最短边长大于等于P

             2. u -> 1

             显然 , 我们要求所有这样的路径中distu的最小值

             不妨先用Dijkstra算法求出单源最短路 , 然后求出kruskal重构树

             对于每组询问 , 将v在kruskal重构树上倍增 , 倍增到一个深度最小的点且该点的权值最小

             那么答案即为这棵子树中dist的最小值

             时间复杂度 : O(T(N+M+Q)logN)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 10;
    const int M = 4e5 + 10;
    const int MAXLOG = 20;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const ll inf = 1e18;
    
    struct info
    {
        int u , v , w;
        int h;
    } a[M];
    
    struct edge
    {
        int to , nxt;
    } e[M << 1];
    
    int n , m , tot , q , s , k , cnt;
    int head[N << 1] , val[N << 1] , father[N << 1][MAXLOG] , depth[N << 1] , fa[N << 1];
    ll dist[N << 1] , mn[N << 1];
    vector< pair<int , int> > G[N];
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(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 dijkstra(int s)
    {
        static bool visited[N << 1];
        priority_queue< pair<ll , int> , vector< pair<ll , int> > , greater< pair<ll , int> > > q;
        q.push(make_pair(0 , s));
        for (int i = 1; i <= n; i++) 
        {
            dist[i] = inf;
            visited[i] = false;
        }
        dist[s] = 0;
        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 to = G[cur][i].first , w = G[cur][i].second;
                if (dist[cur] + w < dist[to])
                {
                    dist[to] = dist[cur] + w;
                    q.push(make_pair(dist[to] , to));
                }
            }
        }
    }
    inline bool cmp(info a , info b)
    {
        return a.h > b.h;
    }
    inline void dfs(int u , int par)
    {
        father[u][0] = par;
        depth[u] = depth[par] + 1;
        for (int i = 1; i < MAXLOG; i++)
            father[u][i] = father[father[u][i - 1]][i - 1];
        if (!head[u]) // leaf
        {
            mn[u] = dist[u];
            return;
        }
        mn[u] = inf;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (v != par) dfs(v , u);
            chkmin(mn[u] , mn[v]);
        }
    }
    inline int getroot(int x)
    {
        if (fa[x] == x) return x;
        else return fa[x] = getroot(fa[x]);
    }
    inline void addedge(int u , int v)
    {
        ++tot;
        e[tot] = (edge){v , head[u]};
        head[u] = tot;
    }
    inline void kruskal()
    {
        int tot = 0;
        cnt = n;
        for (int i = 1; i <= n; i++) fa[i] = i;
        for (int i = 1; i <= m; i++)
        {        
            int fu = getroot(a[i].u) , fv = getroot(a[i].v);
            if (fu != fv)
            {
                fa[fu] = fv;
                addedge(++cnt , fu);
                addedge(cnt , fv);
                val[cnt] = a[i].h;
                fa[fu] = fa[fv] = fa[cnt] = cnt;
                ++tot;
            } 
            if (tot == n - 1) break;
        } 
        dfs(cnt , 0);
    }
     
    int main()
    {
        
        int T;
        read(T);
        while (T--)
        {
            read(n); read(m);    
            tot = 0;
            memset(head , 0 , sizeof(head));
            for (int i = 1; i <= n; i++) G[i].clear();
            for (int i = 1; i <= m; i++)
            {
                read(a[i].u);
                read(a[i].v);
                read(a[i].w);
                read(a[i].h);
                G[a[i].u].push_back(make_pair(a[i].v , a[i].w));
                G[a[i].v].push_back(make_pair(a[i].u , a[i].w));
            }
            sort(a + 1 , a + m + 1 , cmp);
            dijkstra(1);
            kruskal();
            read(q); read(k); read(s);
            int lastans = 0;
            while (q--)
            {
                int v0 , p0;
                read(v0); read(p0);
                int v = (v0 + 1ll * k * lastans - 1) % n + 1 , 
                    p = (p0 + 1ll * k * lastans) % (s + 1);
                for (int i = MAXLOG - 1; i >= 0; i--)
                {
                    if (depth[father[v][i]] > 0 && val[father[v][i]] > p)
                        v = father[v][i];
                }
                printf("%lld
    " , lastans = mn[v]);
            }
        }
        
        return 0;
    }

             

  • 相关阅读:
    被下属骂,记一次矛盾升级——有心无心,蝴蝶效应?
    技术管理进阶——团队合并、解散怎么办?
    “技术转产品”比产品更恶心的几个点
    javaScript系列 [43]TS、Class and ES5
    javaScript系列 [42]node中 require函数的加载过程
    javaScript系列 [52]模板引擎的实现逻辑
    Base64简单介绍
    异或运算(XOR)
    javaScript系列 [51]Rollup 打包器
    javaScript系列 [49] ast && render
  • 原文地址:https://www.cnblogs.com/evenbao/p/10372257.html
Copyright © 2020-2023  润新知