zoukankan      html  css  js  c++  java
  • 题解 T28305 【yizimi的旅游景点】

    题目链接这里!!!

    AC军团月赛题目地址这里!!!正比例函数的旅游景点

    题目翻译

    我依然不会告诉你题目的难度有一半是读题

    其实就是给定一个图中一部分点,给定一部分边,先让你求这之中的最小生成树,然后再这个树的基础上求关于所有点和所有边的最大生成树。

    好用的最小生成树模板

    看到这里我觉得大部分dalao就可以喊着“这出题人语文真差而且这道题真水”去写代码秒题了

    如果您还往下看,只有两种可能:

    1.yizimi的语文太菜了,题目翻译还是看不懂
    
    2.不会写代码诶
    

    好,基本上就没别的弯路,上代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    #define go(i, j, n, k) for (int i = j; i <= n; i += k)
    #define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
    #define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
    #define mn 20020
    #define mm 200010
    #define inf 1 << 30
    #define ll long long
    #define ld long double
    #define fi first
    #define se second
    #define root 1, n, 1
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define bson l, r, rt
    inline int read()
    {
        int f = 1, x = 0;
        char ch = getchar();
        while (ch > '9' || ch < '0')
        {
            if (ch == '-')
                f = -f;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9')
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    inline void write(int x)
    {
        if (x < 0)
            putchar('-'), x = -x;
        if (x > 9)
            write(x / 10);
        putchar(x % 10 + '0');
    }
    //This is AC head above...
    int n, m;
    int ans, tot, cnt;
    bool b[mn];
    struct edge
    {
        int u, v, w, p;
        bool used;
    } e[mm];
    inline bool cmp1(edge a, edge b)
    {
        return a.w < b.w;
    }
    inline bool cmp2(edge a, edge b)
    {
        return a.w > b.w;
    }
    int father[mn];
    inline int findx(int x)
    {
        return father[x] == x ? x : father[x] = findx(father[x]);
    }
    inline void mergex(int x, int y)//随机合并大法好
    {
        int xx = findx(x);
        int yy = findx(y);
        if (xx == yy)
            return;
        srand((unsigned)time(NULL));//随机合并
        if (rand() % 2)
        {
            father[xx] = yy;
        }
        else
        {
            father[yy] = xx;
        }
    }
    inline void Krus()//最小生成树
    {
        go(i, 1, n, 1)
            father[i] = i;
        sort(e + 1, e + m + 1, cmp1);
        go(i, 1, m, 1)
        {
            if (b[e[i].u] && b[e[i].v] && findx(e[i].u) != findx(e[i].v) && e[i].p == 1 && !e[i].used)
            {
                ans += e[i].w;
                mergex(e[i].u, e[i].v);
                e[i].used = true;
                cnt++;
            }
            if (cnt == tot - 1)
                return;
        }
    }
    inline void Krub()//最大生成树
    {
        sort(e + 1, e + m + 1, cmp2);
        go(i, 1, m, 1)
        {
            if (findx(e[i].u) != findx(e[i].v) && !e[i].used)
            {
                ans += e[i].w;
                mergex(e[i].u, e[i].v);
                e[i].used = true;
                cnt++;
            }
            if (cnt == n - 1)
                return;
        }
    }
    int main()
    {
        //freopen("002.in", "r", stdin);
        //freopen("002.out", "w", stdout);
        n = read(), m = read();
        go(i, 1, n, 1)
        {
            b[i] = read();
            //cin >> b[i];
            //scanf("%d", &b[i]);
            if (b[i])
                tot++;
        }
        go(i, 1, m, 1)
        {
            e[i].u = read(), e[i].v = read(), e[i].w = read(), e[i].p = read(), e[i].w *= e[i].p, e[i].used = false;
            //cin >> e[i].u >> e[i].v >> e[i].w >> e[i].p;
            //scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].w, &e[i].p);
            //e[i].w *= e[i].p, e[i].used = false;
        }//这里你可以试试cin,保证慢死
        Krus();
        if (cnt != tot - 1)
        {
            cout << -1;
            return 0;
        }
        int ans1 = ans;
        Krub();
        if (cnt != n - 1)
        {
            cout << -1;
            return 0;
        }
        cout << ans1 << " " << ans - ans1;
        return 0;
    }
    
    

    有些大佬看到这里可能会说:

    明明我写对了,为什么会T?

    我只是想说:

    dalao您先看看时限!

    这个题是300ms,如果你用cin大约是600ms(部分点),不开O2都有可能T掉。

    这就是这个题的最大的坑

    读入优化大法好

    NOIP2018并不是结束,而是开始
  • 相关阅读:
    YAML 语法小结
    小程序之脚本语言
    小程序WXML 使用小结
    微信小程序 js逻辑
    小程序开发1
    联想Y7000安装Ubuntu16.04/Win10双系统,wifi问题,显卡驱动和CUDA10安装
    VS2015中配置Eigen
    联想Y700安装显卡驱动和CUDA8.0
    php微信生成微信公众号二维码扫描进入公众号带参数
    Y7000 (1)安装ubuntu1604遇到的问题
  • 原文地址:https://www.cnblogs.com/yizimi/p/10056230.html
Copyright © 2011-2022 走看看