hdu 6184 Counting Stars(三元环计数)

题意:

给一张n个点m条边的无向图,问有多少个\(A-structure\)

其中\(A-structure\)满足\(V=(A,B,C,D)\) && \(E=(AB,BC,CD,DA,AC)\)

显然\(A-structure\)是由两个有公共边的三元环构成的

\(1 <=n <= 1e5\)

\(1 <= m <= min(2e5,n*(n-1)/2)\)

思路:

三元环计数

做法1、

①统计每个点的度数

②入度\(<=sqrt(m)\)的分为第一类,入度\(>sqrt(m)\)的分为第二类

③对于第一类,暴力每个点,然后暴力这个点的任意两条边,再判断这两条边的另一个端点是否连接

因为\(m\)条边最多每条边遍历一次,然后暴力的点的入度\(<=sqrt(m)\),所以复杂度约为\(O(msqrt(m))\)

④对于第二类,直接暴力任意三个点,判断这三个点是否构成环,因为这一类点的个数不会超过\(sqrt(m)\)个,所以复杂度约为\(O(sqrt(m)^3)=O(msqrt(m))\)

⑤判断两个点是否连接可以用set,map和Hash都行,根据具体情况而行

这种做法建的是双向边,常数很大

更优的做法2、建有向边 复杂度为\(O(msqrt(m))\)

对所有边按照两端点的度数定向,度数小的往度数大的走,度数相同则按编号小到大走,这样定向后

可以保证是个有向无环图。

为什么呢,要想定向存在环,则这个环上的点度数必须相同,由于保证了编号从小到大走

所以是不可能存在环的。

这样定向同时还保证了每个点的出度不超过\(sqrt(m)\),很容易证明,如果存在一个点出度超过了\(sqrt(m)\),则说明存在其他\(sqrt(m)\)个点的度数\(>sqrt(m)\),算起来超过边数\(m\)了。

对于这道题,我们在求三元环的时候,统计一下每条边有多少对点能构成三元环,\(C(cnt,2)\)累计一下即可

做法1、

#include<bits/stdc++.h>
#define LL long long using namespace std;
void read(int &x){
x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
}
const int N = 1e5 + 10;
set<LL> g;
int deg[N];
vector<int> G[N];
int vis[N],vi[N];
int main(){ int n, m, u, v, Sz;
while(scanf("%d%d",&n,&m) != EOF){
Sz = sqrt(m + 0.5);
g.clear();
for(int i = 1;i <= n;i++){
vis[i] = vi[i] = deg[i] = 0;
G[i].clear();
}
for(int i = 0;i < m;i++){
scanf("%d%d",&u,&v);
g.insert(u + 1LL * v * n);
g.insert(v + 1LL * u * n);
deg[u]++,deg[v]++;
G[u].push_back(v);
G[v].push_back(u);
}
LL ans = 0;
for(int u = 1;u <= n;u++){
vis[u] = 1;
for(auto v:G[u]) vi[v] = u;
for(auto v:G[u]){
int cnt = 0;
if(vis[v]) continue;
if(deg[v] <= Sz){
for(auto vv:G[v]){
if(vi[vv] == u) cnt++;
}
}else{
for(auto vv:G[u]){
if(g.find(1LL * v * n + vv) != g.end()) cnt++;
}
}
ans += 1LL * cnt * (cnt - 1) / 2;
}
}
printf("%lld\n",ans);
}
return 0;
}

做法二、

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
void read(int &x){
x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
}
const int N = 1e5 + 10;
set<LL> g;
int deg[N];
vector<pair<int,int> > G[N];
int vi[N];
int X[N * 2],Y[N * 2],cnt[N],pos[N];
int main(){
int n, m, u, v, Sz;
while(scanf("%d%d",&n,&m) != EOF){
Sz = sqrt(m);
for(int i = 1;i <= n;i++){
vi[i] = deg[i] = pos[i] = 0;
G[i].clear();
}
g.clear();
int tot = 0;
for(int i = 0;i < m;i++){
scanf("%d%d",&X[i],&Y[i]);
u = X[i],v = Y[i];
deg[u]++,deg[v]++;
}
for(int i = 0;i < m;i++){
cnt[i] = 0;
if(deg[X[i]] < deg[Y[i]]) G[X[i]].push_back(make_pair(Y[i],i));
else if(deg[Y[i]] < deg[X[i]]) G[Y[i]].push_back(P(X[i],i));
else{
if(X[i] < Y[i]) G[X[i]].push_back(P(Y[i],i));
else G[Y[i]].push_back(P(X[i],i));
}
}
LL ans = 0;
for(int i = 0;i < m;i++){
u = X[i],v = Y[i];
for(auto vp:G[u]) pos[vp.first] = vp.second,vi[vp.first] = i + 1;
for(auto vp:G[v]){
int vv = vp.first;
if(vi[vv] == i + 1){
cnt[i]++;
cnt[pos[vv]]++;
cnt[vp.second]++;
}
}
}
for(int i = 0;i < m;i++) ans += 1LL * cnt[i] * (cnt[i] - 1) / 2;
printf("%lld\n",ans);
}
return 0;
}

[hdu 6184 Counting Stars(三元环计数)的更多相关文章

  1. HDU 6184 Counting Stars

    Problem Description Little A is an astronomy lover, and he has found that the sky was so beautiful!S ...

  2. HDU 6184 Counting Stars 经典三元环计数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6184 题意: n个点m条边的无向图,问有多少个A-structure 其中A-structure满足V ...

  3. 【刷题】HDU 6184 Counting Stars

    Problem Description Little A is an astronomy lover, and he has found that the sky was so beautiful! ...

  4. Codechef SUMCUBE Sum of Cubes 组合、三元环计数

    传送门 好久没有做过图论题了-- 考虑\(k\)次方的组合意义,实际上,要求的所有方案中导出子图边数的\(k\)次方,等价于有顺序地选出其中\(k\)条边,计算它们在哪一些图中出现过,将所有方案计算出 ...

  5. 【BZOJ5332】[SDOI2018]旧试题(数论,三元环计数)

    [BZOJ5332][SDOI2018]旧试题(数论,三元环计数) 题面 BZOJ 洛谷 题解 如果只有一个\(\sum\),那么我们可以枚举每个答案的出现次数. 首先约数个数这个东西很不爽,就搞一搞 ...

  6. loj#6076「2017 山东一轮集训 Day6」三元组 莫比乌斯反演 + 三元环计数

    题目大意: 给定\(a, b, c\),求\(\sum \limits_{i = 1}^a \sum \limits_{j = 1}^b \sum \limits_{k = 1}^c [(i, j) ...

  7. BZOJ.5407.girls/CF985G. Team Players(三元环计数+容斥)

    题面 传送门(bzoj) 传送门(CF) \(llx\)身边妹子成群,这天他需要从\(n\)个妹子中挑出\(3\)个出去浪,但是妹子之间会有冲突,表现为\(i,j\)之间连有一条边\((i,j)\), ...

  8. LOJ2565 SDOI2018 旧试题 莫比乌斯反演、三元环计数

    传送门 这道题的思路似乎可以给很多同时枚举三个量的反演题目提供一个很好的启发-- 首先有结论:\(d(ijk) = \sum\limits_{x|i}\sum\limits_{y|j}\sum\lim ...

  9. hdu6184 Counting Stars 【三元环计数】

    题目链接 hdu6184 题解 题意是让我们找出所有的这样的图形: 我们只需要求出每条边分别在多少个三元环中,记为\(x\),再然后以该点为中心的图形数就是\({x \choose 2}\) 所以我们 ...

随机推荐

  1. ojdbc14_g.jar与ojdbc14.jar区别

    在低级JDK版本1.2与1.3中使用的驱动,class12.jar,虽然实际上在1.4,1.5中使用大部分情况也是OK的 ojdbc14.jar (1,545,954 bytes) - classes ...

  2. Django objects.values

    values(*fields) 返回一个ValuesQuerySet —— QuerySet 的一个子类,迭代时返回字典而不是模型实例对象. 每个字典表示一个对象,键对应于模型对象的属性名称. 下面的 ...

  3. PHP语言开发微信公众平台(订阅号)之curl命令(补充)

    在之前的一篇随笔中,博主在调用curl命令上传文件时会经常出现上传方法过时的情况.如下图所示: 所以,我们只需要把上传方法换成创建CURLFile 类即可.如下所示 $ch = curl_init() ...

  4. CUDA 深入浅出谈[转]

    CUDA 深入浅出谈           “CUDA 是 NVIDIA 的 GPGPU 模型,它使用 C 语言为基础,可以直接以大多数人熟悉的 C 语言,写出在显示芯片上执行的程序,而不需要去学习特定 ...

  5. 日期插件kalendae,遇到的一些问题

    1.日期中文显示 /*_months : 'January_February_March_April_May_June_July_August_September_October_November_D ...

  6. 【dp】最大乘积

    题目描述] 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸 ...

  7. servelet跳转页面的路径中一直包含sevelet的解决办法

    解决办法1: 在web.xml配置文件中修改: <servlet-mapping> <servlet-name>LoginServelet</servlet-name&g ...

  8. 学习笔记 - Manacher算法

    Manacher算法 - 学习笔记 是从最近Codeforces的一场比赛了解到这个算法的~ 非常新奇,毕竟是第一次听说 \(O(n)\) 的回文串算法 我在 vjudge 上开了一个[练习],有兴趣 ...

  9. Redis Sentinel 介绍

    Redis Sentinel   sentinel的功能: 监控:sentinel节点定期检测redis数据节点,其余sentinel节点是否可达. 通知:sentinel 节点会将故障转移结果通知给 ...

  10. 第一课、安装登录CentOS7

    一.学习之初 1.学习这个课程的目的是,高薪就业,搞运维. 2.应该在宁波发展. 3.大概给自己定的计划是4个月能学习2遍. 4.学好之后就跳槽. 5.2年左右的时间要达到1.5W争取. 学习方法: ...