题意:有一张 $n$ 个点$ m $条边的连通图。有$Q$ 次询问。每次询问给出 $k[i]$ 条边,问这些边能否同时出现在一棵最小生成树上。$n,m,Q,\sum k\le 500000$。


这题利用到了最小生成树的一个性质,可以结合我记的最小生成树笔记。在加入所有权值前$i-1$大的边后,目前的权值第$i$大的一些边不管怎么加,连通性都是一样的,也就是连通块内的点集都是一样的,只不过有一些剩下的边或者连接两个块内点的边不合法罢了。于是可以在kruskal的时候先处理出对于每条边,他连接的两个连通块是什么(以当时的角度记录块上并查集祖先)。然后处理询问的时候,排序后对于权值相同的边,用并查集判断他们连接的连通块是否有环,即合不合法即可。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=5e5+;
int n,m,q,k;
struct thxorz{
int u,v,w,id;
inline bool operator <(const thxorz&A){return w<A.w;}
}e[N];
struct stothx{int fx,fy,w;}g[N];
int anc[N];
int find_anc(int x){return x==anc[x]?x:anc[x]=find_anc(anc[x]);} inline void Kruskal(){
sort(e+,e+m+);
for(register int i=;i<=n;++i)anc[i]=i;
for(register int i=,st=;i<=m;++i)if(e[i].w^e[i+].w){
for(register int j=st;j<=i;++j)
g[e[j].id].fx=find_anc(e[j].u),g[e[j].id].fy=find_anc(e[j].v);//dbg(e[j].id),dbg2(g[e[j].id].fx,g[e[j].id].fy);
for(register int j=st;j<=i;++j)
anc[find_anc(g[e[j].id].fx)]=find_anc(g[e[j].id].fy);
st=i+;
}
}
int a[N],vis[N],cnt;
inline bool cmp(int a,int b){return g[a].w<g[b].w;}
inline void Query(){
read(k);for(register int i=;i<=k;++i)read(a[i]);a[k+]=;
sort(a+,a+k+,cmp);
for(register int i=,st=;i<=k;++i)if(g[a[i]].w^g[a[i+]].w){
for(register int j=st;j<=i;++j){//dbg(a[j]);
int fx=find_anc(g[a[j]].fx),fy=find_anc(g[a[j]].fy);//dbg2(fx,fy);
if(fx^fy)anc[fx]=fy,vis[++cnt]=fx;
else{while(cnt)anc[vis[cnt]]=vis[cnt],--cnt;puts("NO");return;}
}
st=i+;
while(cnt)anc[vis[cnt]]=vis[cnt],--cnt;
}
puts("YES");
} int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(m);
for(register int i=;i<=m;++i)read(e[i].u),read(e[i].v),g[i].w=read(e[i].w),e[i].id=i;
Kruskal();
for(register int i=;i<=n;++i)anc[i]=i;
read(q);while(q--)Query();
return ;
}

总结:要理解kruskal本质和其性质,从而进行改造,注意连通块性质。

CF892E Envy[最小生成树]的更多相关文章

  1. CF891C Envy 最小生成树/虚树

    正解:最小生成树/虚树 解题报告: 传送门! sd如我就只想到了最暴力的想法,一点儿优化都麻油想到,,,真的菜到爆炸了QAQ 然后就分别港下两个正解QAQ 法一,最小生成树 这个主要是要想到关于最小生 ...

  2. 【CF891C】Envy(最小生成树)

    [CF891C]Envy(最小生成树) 题面 Codeforces 洛谷 题解 考虑\(MST\)的构建过程,对于所有权值相同的边一起考虑. 显然最终他们连出来的结果是固定的. 把连边改为把联通块联通 ...

  3. 【CF891C】Envy 离线+最小生成树

    [CF891C]Envy 题意:给你一个图,边有边权,每次询问给你一堆边,问你是否存在一个原图的最小生成树包含给出的所有边.n,m,q<=100000 题解:思路很好的题. 首先有一个非常重要的 ...

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

    For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph of G that con ...

  5. CF891C Envy【最小生成树】

    题目链接 我们知道,根据Kruskal的贪心,对于最小生成树,每一种权值的边数是一样的,而且如果将\(\leq x\)的边做最小生成树,合法方案的联通性是一样的.所以我们可以对于所有边分开考虑. 对于 ...

  6. Codeforces 891C Envy

    Envy 感觉这种最小生成树上的啥题都差不多的解法.. #include<bits/stdc++.h> #define LL long long #define fi first #def ...

  7. Codeforces 891C Envy(MST + 并查集的撤销)

    题目链接  Envy 题意  给出一个连通的无向图和若干询问.每个询问为一个边集.求是否存在某一棵原图的最小生成树包含了这个边集. 考虑$kruskal$的整个过程, 当前面$k$条边已经完成操作的时 ...

  8. 代码的坏味道(18)——依恋情结(Feature Envy)

    坏味道--依恋情结(Feature Envy) 特征 一个函数访问其它对象的数据比访问自己的数据更多. 问题原因 这种气味可能发生在字段移动到数据类之后.如果是这种情况,你可能想将数据类的操作移动到这 ...

  9. 最小生成树(Kruskal算法-边集数组)

    以此图为例: package com.datastruct; import java.util.Scanner; public class TestKruskal { private static c ...

随机推荐

  1. vue中的样式穿透

    参考一下的文章即可: https://www.cnblogs.com/karthuslorin/p/9038854.html http://www.php.cn/js-tutorial-399072. ...

  2. 关于bootstrap的响应式插件respond.min.js在IE8下出现:拒绝访问。respond.min.js,行: 5,列: 746报错问题

    本地在IE8浏览器下测试兼容性的时候,出现了以下的报错: 该问题在bootstrap的官网有介绍:https://v3.bootcss.com/getting-started

  3. ZOJ Problem Set - 1007

    1.参考这个吧,一道数学公式题,还没看懂...好像需要把公式变形出来,先略过. http://dengbaoleng.iteye.com/blog/1504940

  4. TP5之事务处理

    事务: 执行完A事件然后执行B事件,AB事件都执行完才算完成.可是有时候由于某些因素,A事件执行完,还没来得及执行B事件.怎么办?就需要回到A事件执行前.这种事情多见于电商支付功能. mysql事务要 ...

  5. Appendix 2- Lebesgue integration and Reimann integration

    Lebesgue integration and Reimann integration: Reimann: Split up the axis into equal intervals, then ...

  6. 【转帖】安卓的Bionic 简介

    https://blog.csdn.net/yongyu_it/article/details/52574797 google 自己实现了一套libc 的库函数 比glibc 要小一些 占用内存也小. ...

  7. ABP创建应用服务

    原文作者:圣杰 原文地址:ABP入门系列(4)——创建应用服务 在原文作者上进行改正,适配ABP新版本.内容相同 1. 解释下应用服务层 应用服务用于将领域(业务)逻辑暴露给展现层.展现层通过传入DT ...

  8. 斜率优化DP(转载)

    转载自:https://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html 我们知道,有些DP方程可以转化成DP[i]=f[j]+x[i] ...

  9. redis 主从、哨兵、集群

    出处: redis主从复制和哨兵 Redis集群方式共有三种:主从模式,哨兵模式,cluster(集群)模式 一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步 ...

  10. 牛客 109B 好位置 (字符串水题)

    大意: 给定字符串$s1,s2$, 对于$s1$中所有与$s2$相等的子序列$t$, $t$在$s1$中的下标定义为好位置. 求$s1$是否所有位置都是好位置. 显然$s1$的前缀要与$s2$相等, ...