• 题解 LOJ3275 「JOISC 2020 Day2」有趣的 Joitter 交友


    把两个互相关注的人缩成一个集合。如果对于两个集合A,B,集合A中某个人关注了集合B中的某个人,集合B中的某个人也关注了集合A中的某个人(这四个人可以互不相同),则把A,B缩成一个大集合。以此类推。例如下图中,原有A,B两个集合,后来加入了(a ightarrow c),(b ightarrow d)两条边。此时如果搞活动,会带来(a ightarrow d),(d ightarrow a)两新的条边。接下来会有连锁反应,其结果是(a),(b),(c),(d)两两相互关注。这就是为什么我们可以把图缩成若干个“集合”,然后直接在集合间连边。

    考虑一个集合(S),大小为(sz(S))。如果有(ine(S))条边连向这个集合(连向集合内的至少一个点),则集合(S)对答案的贡献是:(sz(S)(sz(S)-1)+sz(S)ine(S))

    我们用并查集维护这些集合。用( exttt{set})维护连向每个集合的边(ine)

    考虑如何处理加边操作。加入一条边(x ightarrow y)时,分三种情况讨论:

    • 如果(x),(y)已经在同一个集合内,则什么都不用做。
    • 如果(y)所在集合已经有了连向(x)所在集合的边,则把两个点所在集合合并。
    • 其他情况下,更新(y)所在集合的(ine)即可。

    发现要判断:(y)所在集合是否有连向(x)所在集合的边。我们给每个集合再开两个( exttt{set}),记录这个集合的入边、出边。注意这里的“出/入边”指的是集合之间的边。

    合并两个集合时,用启发式合并。维护好每个集合相关信息的若干个( exttt{set})即可。注意,合并时可能会造成连锁反应,所以我们用一个队列,只要队列不为空,就不断取出队头,进行合并。

    时间复杂度(O(nlog^2n))

    参考代码

  • 相关阅读:
    Indy的TCPServer到底能支持多少个连接
    Delphi TStream 详细介绍
    WebAPI下的如何实现参数绑定
    使用 Weinre 调试移动网站及 PhoneGap 应用
    面向对象的三大特征:封装、继承、多态
    轻量级前端MVVM框架avalon
    三种工厂模式的分析以及C++实现
    简单实现TCP下的大文件高效传输
    Nunit NMock Ncover单元测试
    算法实践——数独的基本解法
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/12619714.html
Copyright © 2020-2023  润新知