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

无向图三元环计数

时间:2024-07-05 19:41:19浏览次数:8  
标签:原图 int sqrt 计数 无向 出边 三元 out deg

Description

P1989 无向图三元环计数

给定简单无向图 \(G=(V,E)\),求其三元环个数,其中 \(\lvert V\rvert\leq10^5,\lvert E\rvert\leq 2\times 10^5\)。

Solution

考虑给每一个边定一个方向。具体地,对于原图的一条边 \(E=(u,v)\),有

  • 若 \(\deg_u>\deg_v\) 或 \(\text{deg}_u=\text{deg}_v\land u<v\),则 \(u\to v\)
  • 否则 \(v\to u\)

给边定完方向后,原图变成了一个有向无环图 。

注意到原图中的三元环一定与对应有向图中所有形如 \(E'=(u\to v,u\to w,v\to w)\) 的子图一一对应。

只需要枚举 \(u\) 的出边,再枚举 \(v\) 的出边,然后检查 \(w\) 是否为 \(u\) 指向的点即可。时间复杂度为 \(\mathcal O(m\sqrt m)\)。

  • 为什么时间复杂度为 \(O(m\sqrt m)\)​?

首先在在枚举 \(u\) 的出边时打上 \(u\) 的时间戳,这样在枚举 \(v\) 的出边时可以 \(O(1)\) 判断。

那么考虑每一条边 \(u\to v\) 的贡献为 \(out_v\),所以总复杂度为 \(\sum\limits_{i=1}^{m} out_{v_i}\),其中 \(v_i\) 是第 \(i\) 条边指向的点, \(out_v\) 是点 \(v\)​ 的出度。

对于每一个点 \(v\) 分情况讨论。

  1. 当在原图上 \(\deg_v\leq\sqrt m\) 时,由于新图每个节点的出度不可能大于原图的度数,所以 \(out_v=O(\sqrt m)\)。
  2. 当在原图上 \(\deg_v>\sqrt m\) 时,注意到它只能向原图中度数不小于它的点连边,又因为原图中所有的点的度数和为 \(O(m)\),所以原图中 \(\deg>\sqrt m\) 的点只有 \(O(\sqrt m)\) 个。因此 \(v\) 的出边只有 \(O(\sqrt m)\) 条,即 \(out_v=O(\sqrt m)\)。

综上所有点的度数都为 \(O(\sqrt m)\),总复杂度就为 \(O(m\sqrt m)\)。

Code

const int N=1e5+5;
int n,m,deg[N],vis[N],ans;
struct E{int u,v;}e[N*3];
vector<int>G[N];

signed main(){
    n=read();m=read();
    for(int i=1;i<=m;i++){
        e[i]=(E){read(),read()};
        deg[e[i].u]++;deg[e[i].v]++;
    }
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v;
        if(deg[u]<deg[v] or (deg[u]==deg[v] and u>v))
            swap(u,v);
        G[u].eb(v);
    }
    for(int u=1;u<=n;u++){
        for(auto v:G[u])
            vis[v]=u;
        for(auto v:G[u])
            for(auto w:G[v])
                if(vis[w]==u)
                    ans++;
    }
    write(ans);
    return 0;
}

标签:原图,int,sqrt,计数,无向,出边,三元,out,deg
From: https://www.cnblogs.com/QcpyWcpyQ/p/18286457

相关文章

  • 三菱FX PLC入门之定时器和计数器
    PLC中,定时器和计数器是两个非常主要的编程元件,是PLC程序编制不可或缺的环节。我在之前的文章中简单地扯了一下这两个元件,而现在就是揭秘时刻了,让我们一起来看看它们的庐山真面目吧!一、定时器说到定时器,其实我们生活中就有很多它的应用,例如洗衣机的定时选择,烤箱的定时旋......
  • 竞赛图 SCC 计数(ARC163D)
    我们先端上来一个美味的结论。对于一张有\(n\)个点的竞赛图\(G\),它的SCC数量等于:将\(G\)的\(n\)个点划分为两个点集\(S\)和\(T\),且要求\(|T|>0\),对于任意的\(u\inS\)和\(v\inT\),\(u\)和\(v\)之间的连边方向为\(u\tov\)的方案数。考虑将图\(G\)进行......
  • 前端学习-flutter学习-002-计数器示例学习
    学习参考链接拆解代码学习Material是一种标准的移动端和web端的视觉设计语言,Flutter默认提供了一套丰富的Material风格的UI组件。//导入了MaterialUI组件库。import'package:flutter/material.dart';main函数为应用程序的入口。main函数中调用了runApp方法......
  • 迭代器协议、可迭代对象(迭代器)、三元表达式、生成器
    今天说的这老几位可是老牛逼了,认真看,咱们挨个介绍哈。1、迭代器协议(1)有一个next()方法(2)只能往后走不能往前退2、可迭代对象可迭代对象又叫做迭代器,什么是可迭代对象呢?很简单,满足迭代器协议的对象就是可迭代对象。说白了,就是满足前面那两条:有一个next()方法,只能往后走不能往......
  • 题解 - 数字计数
    题目思路简析正解是数位dp,但是我不太会,所以我打分块。考虑从\(10^6\)到\(2\times10^6\)和从\(3\times10^6\)到\(4\times10^6\),其中真正的区别只有观察到数据范围是\(10^{12}\),分为一些块,每块长\(10^6\)会比较均衡,所以共有\(10^6\)个块。最差情况是\(n=10^6+1......
  • 题解 - 数字计数
    题目思路简析正解是数位dp,但是我不太会,所以我打分块。考虑从\(10^6\)到\(2\times10^6\)和从\(3\times10^6\)到\(4\times10^6\),其中真正的区别只有观察到数据范围是\(10^{12}\),分为一些块,每块长\(10^6\)会比较均衡,所以共有\(10^6\)个块。最差情况是\(n=10^6+1......
  • 14.计数器拓展练习
    (1)Visio视图:(2)Verilog代码:modulecounter_ten(clk,reset_n,led_out);inputclk;inputreset_n;outputregled_out;//0.5s=500_000_000ns=20ns*25_000_000;需要25位的寄存器去储存。reg[24:0]cnt;regen_cnt;regcn......
  • 13.计数器设计、标志脉冲信号的使用
    (1)设计定义:设计一个计数器模块,实现每0.5秒跳转一次的功能,可以用LED灯的翻转来体现,要求初始状态为LED熄灭。(2)visio视图:(3)Verilog代码:modulecounter(clk,reset_n,led_out);inputclk;inputreset_n;outputregled_out;//0.5s=500_000_000ns=......
  • 样本空间的计数
    前言在统计样本空间数时,需要考虑是否有顺序和是否放回,同时请注意列举法、描述法,表格法,树状图的合理运用。这些方法都是高一初次学习需要切实掌握的方法,等到了高二或者高三,对思维的要求提高以后,更多的会用到加法计数原理和乘法计数原理这两个计数原理,更多见的是使用排列数和组合数......
  • verilog写12 小时时钟(带上午/下午指示器)计数器(HDLbits Count clock)
    Createasetofcounterssuitableforuseasa12-hourclock(witham/pmindicator).Yourcountersareclockedbyafast-running clk,withapulseon ena wheneveryourclockshouldincrement(i.e.,oncepersecond).reset resetstheclockto12:00AM.......