码迷,mamicode.com
首页 > 其他好文 > 详细

CF891C Envy

时间:2019-03-01 15:29:29      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:clear   cpp   while   set   swap   wap   getc   efi   相同   

题面

题解

首先要知道两个性质:

  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

标签:clear   cpp   while   set   swap   wap   getc   efi   相同   

原文地址:https://www.cnblogs.com/cj-xxz/p/10456493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!