题解 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掉。

这就是这个题的最大的坑

读入优化大法好

posted @ 2018-12-02 23:21  yizimi  阅读(211)  评论(0编辑  收藏  举报