首页 > 其他分享 >P1989 无向图三元环计数

P1989 无向图三元环计数

时间:2023-01-04 14:13:22浏览次数:60  
标签:ch int 出度 sqrt 计数 枚举 无向 出点 P1989

P1989 无向图三元环计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

属于是只有大文学家能写出来,我只能抄在积累本上的那种。

考虑给每个点赋权 \(a_u\),权值两两不同,然后给原图定向:

对于原图上的一条边 \((u, v)\),让 \(a\) 小的连向 \(a\) 大的。

不难发现形成的有向图是 DAG,因为如果 \(u \to v \to w \to u\) 就有 \(a_u < a_v < a _w < a_u\),矛盾。

所以原来的三元环在新图中一定是这样一个形态:\((u \to v), (u \to w), (v \to w)\)。没有其他形态,不信你画画看。

我们只要枚举 \(u\) 的出点 \(v\),再枚举 \(v\) 的出点 \(w\),检查 \(w\) 是否是 \(u\) 的出点即可。

只需枚举 \(u\) 时,将 \(u\) 的所有出点打上标记,就可以 \(\mathcal{O}(1)\) 判断 \(w\) 是否为 \(u\) 的出点。

现在,我们将 \(a_u\) 的权值赋为 \((d_u, u)\)。\(d_u\) 表示 \(u\) 在原图上的度数。

这是一个有序数对,比较时优先比较第一维再比较第二维,容易看出,因为第二维的存在,权值有了互异性。

如此以来可以保证:新图中每个点的出度不大于 \(\sqrt m\)。简单证明一下。对于点 \(u\):

  • 如果 \(d_u \le \sqrt m\),显然新图上 \(u\) 的出度不会超过 \(d_u\),所以新出度不大于 \(\sqrt m\);
  • 如果 \(d_u > \sqrt m\),因为 \(\sum d = m\),因此 \(d\) 大于 \(\sqrt{m}\) 的点不会超过 \(\sqrt m\) 个,大于 \(d_u\) 的点则更不会超过 \(\sqrt m\) 个。根据我们的连边规则,新出度也不会大于 \(\sqrt m\)。

枚举 \(u\) 和枚举其出点 \(v\) 的二重循环可看作枚举边,复杂度为 \(m\);而枚举 \(v\) 的出点复杂度为 \(\sqrt m\)。所以,该算法时间复杂度为 \(\Theta(m \sqrt m)\)。

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2023-01-04 13:51:33 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2023-01-04 13:56:20
 */
#include <bits/stdc++.h>
inline int read() {
    int x = 0;
    bool f = true;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-')
            f = false;
    for (; isdigit(ch); ch = getchar())
        x = (x << 1) + (x << 3) + ch - '0';
    return f ? x : (~(x - 1));
}

const int maxn = (int)1e5 + 5;
const int maxm = (int)2e5 + 5;

int d[maxn], us[maxm], vs[maxm];
std :: vector <int> G[maxn];

int t[maxn];

int main() {
    int n = read(), m = read();
    for (int i = 1; i <= m; ++i) {
        int u = read(), v = read();
        us[i] = u;
        vs[i] = v;
        ++d[u];
        ++d[v];
    }

    for (int i = 1; i <= m; ++i) {
        int u = us[i], v = vs[i];
        if (d[u] > d[v])
            std :: swap(u, v);
        else if (d[u] == d[v] && u > v)
            std :: swap(u, v);
        G[u].push_back(v);
    }

    int ans = 0;
    for (int u = 1; u <= n; ++u) {
        for (int v : G[u])
            t[v] = u;
        for (int v : G[u])
            for (int w : G[v])
                if (t[w] == u)   
                    ++ans;
    }
    
    printf("%d\n", ans);
    return 0;
}

标签:ch,int,出度,sqrt,计数,枚举,无向,出点,P1989
From: https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1989.html

相关文章

  • 三(四)元环计数
    无向图三元环计数将边定向,度数少的点连向度数多的点,度数相同时编号小的连向编号大的。这样保证一个点它的出度不会超过$O(\sqrt{m})$(因为原本度数大于$\sqrt{m}$......
  • (组合数学笔记)Pólya计数理论_Part.10_Pólya定理的推广——De Bruijn定理的母函数形式
    文章目录写在前面介绍DeBruijn定理的母函数形式,由此《(组合数学笔记)Pólya计数理论》系列完结。引入与Pólya定理的母函数形式的推导类似,首先引入模式清单的概念,并介绍两个......
  • 三元环计数
    \(\mathcalLink\)枚举一条边\((u,v)\),选择度数较小的点\(v\)暴力扫所有出边即可。一次复杂度\(\mathcalO(out_v)\)可能需要一个Hash。这样做复杂度为\(\mathca......
  • 计数类dp
    例题:整数划分一个正整数\(n\)可以表示成若干个正整数之和,形如:\(n=n_1+n_2+…+n_k\),其中\(n_1≥n_2≥…≥n_k,k≥1\)。我们将这样的一种表示称为正整数\(n\)的一种......
  • Algorithm 2 - 一些数论/组合计数知识
    0.一些前置知识莫比乌斯函数:定义\(\mu(x)\)为:当\(x\)含平方因子,则\(\mu(x)=0\);否则设其有\(p\)个质因子,\(\mu(x)=(-1)^p\)。特别的,\(\mu(1)=1\)。莫比乌斯......
  • 现代细胞计数分析平台丨OMIQ简介
    单细胞分析,变得简单OMIQ是一个现代细胞计数分析平台,它将机器学习和分析管道与经典手动分析的世界连接起来。它允许研究人员在一个软件中完成他们的整个工作流程,从原始......
  • Jmeter——循环控制器中实现Counter计数器的次数重置
    近期在使用Jmeter编写个辅助测试的脚本,用到了多个LoopController和Counter。当时想的思路就是三个可变的数量值,使用循环实现;但第三个可变值的数量次数,是基于第二次循环中......
  • luogu P4002 [清华集训2017]生成树计数
    题面传送门容易想到放到prufer序列上,变成下面的形式。\(\sum\limits_{\sumc_i=n-2}{\frac{(n-2)!}{\prod\limits_{i=1}^{n}{c_i!}}\prod\limits_{i=1}^{n}{a_i^{c_i+1}(......
  • 基于OpenCV实现“钢管计数”算法,基于Csharp编写界面,并实现算法融合【完成】...
    一、DL现状、本例范畴​​​​本例显然属于objectlocalization。二、支撑环境和基本流程这个基本上来说,就是采用百度自己提供的数......
  • 格路计数和反射容斥
    起源:将这个dp式子优化到线性。\[dp_{i,j}=\sum\limits_{k=j+1-b-a}^{j+1}{dp_{i-1,k}}\]考虑一个二维平面上,只能向右边或者上面走。也就是,当你走到\((......