CF891C Envy

Posted cj-xxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF891C Envy相关的知识,希望对你有一定的参考价值。

题面

题解

首先要知道两个性质:

  1. 对于任意权值,最小生成树上该权值的边数是相同的。
  2. 对于任意一个最小生成树,当加完所有权值小于一个任意值的边之后,当前图的连通性是一样的。

于是我们按照权值分开处理,对每一种边的权值的每一个询问都处理一遍即可,这个可以写一个到撤销操作的并查集。

于是这道题目就做完了。

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<vector>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
    int data = 0, w = 1; char ch = getchar();
    while(ch != '-' && (!isdigit(ch))) ch = getchar();
    if(ch == '-') w = -1, ch = getchar();
    while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    return data * w;
}

const int maxn(5e5 + 10);
struct edge { int x, y, w; } e[maxn];
struct qry { int id, x, y, w; };
inline int cmp(const edge &lhs, const edge &rhs) { return lhs.w < rhs.w; }
std::vector<qry> Q[maxn];
int fa[maxn], size[maxn], ans[maxn], n, m, q, stk[maxn], top;
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
inline int merge(int x, int y)
{
    x = find(x), y = find(y);
    if(x == y) return 0;
    if(size[x] > size[y]) std::swap(x, y);
    fa[x] = y, size[y] += size[x], stk[++top] = x;
    return 1;
}

int main()
{
    n = read(), m = read();
    for(RG int i = 1; i <= m; i++)
        e[i] = (edge) {read(), read(), read()};
    q = read();
    for(RG int i = 1, k; i <= q; i++)
    {
        k = read();
        for(RG int j = 1, x; j <= k; j++)
            x = read(), Q[e[x].w].push_back((qry) {i, e[x].x, e[x].y, e[x].w});
    }
    std::sort(e + 1, e + m + 1, cmp);
    for(RG int i = 1; i <= n; i++) size[fa[i] = i] = 1;
    for(RG int i = 1; i <= q; i++) ans[i] = 1;
    for(RG int i = 1; i <= m; i++)
    {
        int val = e[i].w; top = 0;
        for(RG int j = 0; j < (int)Q[val].size(); j++)
        {
            if(!ans[Q[val][j].id]) continue;
            if(j > 0 && Q[val][j].id != Q[val][j - 1].id)
                while(top)
                {
                    int x = stk[top--];
                    size[fa[x]] -= size[x];
                    fa[x] = x;
                }
            if(!merge(Q[val][j].x, Q[val][j].y))
                ans[Q[val][j].id] = 0;
        }
        while(e[i].w == val) merge(e[i].x, e[i].y), ++i;
        if(e[i].w != val) --i;
    }
    for(RG int i = 1; i <= q; i++) puts(ans[i] ? "YES" : "NO");
    return 0;
}

以上是关于CF891C Envy的主要内容,如果未能解决你的问题,请参考以下文章

「CF891C」Envy

[题解] [CF891C] Envy

[CF891C] Envy - Kruskal,并查集

CF 891C Envy 最小生成树+可撤销并查集

CodeForces - 891C: Envy(可撤销的并查集&最小生成树)

惠普 ENVY 16 创意本 评测