• 计蒜客 17417 Highest Tower(思维+图论)


    题解:

    实际上一个可行解即选取长和宽的一个,使得最后每一组选第一维的数值都不同

    在此基础上,使得另一维的和最大。

    然后建立图论模型

    对于每一个方块,在a和b之间连边。

    对于选择的方案,如果选择a->b,那么就是以a为底,b为高

    所以最后的图一定要满足所有点的出度为1(出度为2就有重复了)

    基于这个我们发现只有两种情况。

    1、图中含有环,实际上所有边的方向都是固定的,答案就是每个点的入度*每个点的值加起来。

    2、图中不含环(树的结构),那么实际上可以选取一个点为根,根的答案可以额外计算。所以就选取树中值最大的那个点为根即可。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <map>
    using namespace std;
    const int maxn = 5e5 + 100;
    vector<int> G[maxn];
    map<int, int> M;
    long long m, N, Max, ans;
    int vis[maxn], v[maxn];
    void dfs(int x){
        if(vis[x]) return;
        vis[x] = 1;
        m += G[x].size(); N++; Max = max(Max, (long long)v[x]);
        ans += (G[x].size()-1)*v[x];
        for(auto to : G[x]) dfs(to);
    }
    int n, x, y, tot;
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d %d", &x, &y);
            if(!M[x]){
                M[x] = ++tot;
                v[tot] = x;
            }
            if(!M[y]){
                M[y] = ++tot;
                v[tot] = y;
            }
            G[M[x]].push_back(M[y]);
            G[M[y]].push_back(M[x]);
        }
        memset(vis, 0,   sizeof(vis));
        for(int i = 1; i <= tot; i++){
            if(!vis[i]) {
                N = 0;
                m = 0;
                Max = 0;
                dfs(i);
                if(m/2 == N-1) ans += Max;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    python基础4
    python的基础数据类型和编码
    python的if语句和while循环
    java特殊运算符
    深入理解java集合
    python常用模块
    python函数的参数问题
    集合关系之间的运算
    集合
    可变类型与不可变类型
  • 原文地址:https://www.cnblogs.com/Saurus/p/7637349.html
Copyright © 2020-2023  润新知