zoukankan      html  css  js  c++  java
  • [ICPC2019上海E] Cave Escape

    [ICPC2019上海E] Cave Escape - MST

    Description

    给定一个 (n∗m) 的格子矩阵,其中有一个格子是起点,一个格子是终点。 从起点开始移动,每次能移动到有相邻边的格子中,每个格子都有一个权值 (v),若从点 ((x,y)) 移动到点 ((i,j)),且 ((i,j)) 点未被访问过,则可以获得 (V_{(x,y)}*V_{(i,j)}) 的收益,若移动到终点,可以选择先不出去。一个点可以重复经过,问能够获得的最大价值是多少?(n,m le 1000, v le 100)

    Solution

    转化为最大生成树,暴力建图用 Kruskal 即可

    #include <bits/stdc++.h>
    using namespace std;
    
    int x[1000005], fa[1000005], v[1005][1005];
    const int di[4] = {0, 0, 1, -1};
    const int dj[4] = {1, -1, 0, 0};
    
    void solve()
    {
        int n, m, _, a, b, c, p;
        cin >> n >> m >> _ >> _ >> _ >> _ >> x[1] >> x[2] >> a >> b >> c >> p;
        for (int i = 3; i <= n * m; i++)
            x[i] = (a * x[i - 1] + b * x[i - 2] + c) % p;
        vector<vector<pair<int, int>>> buc(p * p + 2);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                for (int dir = 0; dir < 4; dir += 2)
                {
                    int ii = i + di[dir], jj = j + dj[dir];
                    if (ii == 0 || jj == 0 || ii > n || jj > m)
                        continue;
                    buc[x[(i - 1) * m + j] * x[(ii - 1) * m + jj]].push_back(make_pair((i - 1) * m + j, (ii - 1) * m + jj));
                }
            }
        for (int i = 1; i <= n * m; i++)
            fa[i] = i;
        long long ans = 0;
        vector<pair<int, int>> e;
        for (int i = p * p; i >= 0; i--)
        {
            for (auto t : buc[i])
                e.push_back(t);
        }
        function<int(int)> find = [&](int x) -> int {
            return fa[x] == x ? x : fa[x] = find(fa[x]);
        };
        for (auto [u, v] : e)
        {
            int uu = find(u);
            int vv = find(v);
            int ww = x[u] * x[v];
            if (uu != vv)
            {
                fa[uu] = vv;
                ans += ww;
            }
        }
        cout << ans << endl;
    }
    
    signed main()
    {
        int _, t;
        cin >> t;
        for (int _ = 1; _ <= t; _++)
        {
            cout << "Case #" << _ << ": ";
            solve();
        }
    }
    
  • 相关阅读:
    关于C语言字符串
    进程间通信方式总结
    数据结构(3)-----链表
    Oracle查看用户所在表空间
    oracle linux了解基本命令行
    关于分区技术的索引 index
    oracle闪回表详解
    转:深入学习Oracle分区表及分区索引
    第一章 基本的SQL语句 (SQL基础)
    linux根分区扩容
  • 原文地址:https://www.cnblogs.com/mollnn/p/14571232.html
Copyright © 2011-2022 走看看