传送门

题意:给出一个$N$个点、$M$条边的无向连通图,求有多少组无序数对$(i,j)$满足:割掉第$i$条边与第$j$条边之后,图变为不连通。$N \leq 10^5 , M \leq 3 \times 10^5$


竟然随机化,歪果仁的思想好灵活qwq肯定是数据结构做多了

看起来很像割边,考虑$tarjan$,但是边三连通分量并不是很好实现,而且有很多特殊情况需要判断,所以我们考虑另外的算法

考虑$tarjan$时建出的一棵树。对于它来说,在一个端点在其下方、另一个端点在其上方的的返祖边可以成为它的依靠,因为割掉它,这一条依靠边可以代替它的功能。而对于一条返祖边来说,割掉对于树边是没有影响的,我们就定义它自己为自己的依靠。

这样每一条边都有自己的依靠集合。考虑两条依赖集合相同的边,将它们割掉之后,中间一段的点就会因为上下都没有额外的依靠而使得图不连通。而对于一条依赖集合为空的边(即割边),它选择任何边都可以加入贡献。

所以我们现在需要考虑如何给某一段边加入贡献。然后CC的题解给出的玄学办法是:随机化+树上差分+XOR

我们考虑将给一条返祖边定权值为一个$random$出来的值$t$,然后把所有依靠它的边的依靠集合异或上这个值,这个可以树上差分去做。这样所有的依靠集合就变成了一个数。然后我们判断两条边的依靠集合对应的数是否相等即可。

Because 2^64 is large enough comparing to the range of N and M, don't worry about the probability. :) You will get AC if you implemented correctly.——原题题解

然而我$rand() WA$了好几发qwq

如果随机数种子出了问题的话就看下面这种玄学rand好了

 #include<bits/stdc++.h>
#define CC
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MAXN = ;
struct Edge{
int end , upEd;
}Ed[MAXN * ];
int head[MAXN] , num[MAXN] , dep[MAXN] , fa[MAXN] , N , cntEd , cnt;
unsigned long long point[MAXN] , forS[MAXN * ];
bool vis[MAXN]; #define ll unsigned long long
inline ll rp(){return (1ll*rand())^(1ll*rand())<<^(1ll*rand())<<^(1ll*rand())<<^(1ll*rand())<<;} inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
} void dfs1(int x , int t){
fa[x] = t;
dep[x] = dep[fa[x]] + ;
vis[x] = ;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end])
dfs1(Ed[i].end , x);
else
if(dep[Ed[i].end] > dep[x]){
long long t = rp();
point[x] ^= t;
point[Ed[i].end] ^= t;
forS[++cnt] = t;
}
} void dfs2(int x){
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(fa[Ed[i].end] == x){
dfs2(Ed[i].end);
point[x] ^= point[Ed[i].end];
}
if(x != )
forS[++cnt] = point[x];
} int main(){
#ifdef CC
freopen("TAPAIR.in" , "r" , stdin);
freopen("TAPAIR.out" , "w" , stdout);
#endif N = read();
int M = read();
for(int i = ; i <= M ; i++){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
dfs1( , );
dfs2();
sort(forS + , forS + cnt + );
int p = ;
while(p <= cnt && forS[p] == )
p++;
long long ans = (p - ) * (long long)(p - ) / + (p - ) * (M - p + );
while(p <= cnt){
int beg = p;
while(p <= cnt && forS[p] == forS[beg])
p++;
ans += (long long)(p - beg) * (p - beg - ) / ;
}
cout << ans;
return ;
}

Codechef TAPAIR Counting the important pairs 随机化、树上差分的更多相关文章

  1. Counting The Important Pairs CodeChef - TAPAIR

    https://vjudge.net/problem/CodeChef-TAPAIR 合法的删除方法: 第一种:桥边与其余任意边(1)桥*(桥-1)/2(两条桥边)(2)桥*(m-桥)(桥边+其他边) ...

  2. BZOJ3569 DZY Loves Chinese II(随机化+树上差分+线性基)

    上一题的强制在线版.对图跑出一个dfs树,给非树边赋上随机权值,树边的权值为覆盖他的非树边权值的异或.这样如果某条树边和覆盖他的非树边都被割掉(即图不连通),他们的异或值就为0.每次对询问看有没有子集 ...

  3. Codechef Sad Pairs——圆方树+虚树+树上差分

    SADPAIRS 删点不连通,点双,圆方树 非割点:没有影响 割点:子树DP一下 有不同颜色,所以建立虚树 在圆方树上dfs时候 如果当前点是割点 1.统计当前颜色虚树上的不连通点对,树形DP即可 2 ...

  4. [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  5. P3128 [USACO15DEC]最大流Max Flow(LCA+树上差分)

    P3128 [USACO15DEC]最大流Max Flow 题目描述 Farmer John has installed a new system of  pipes to transport mil ...

  6. [USACO15DEC]最大流Max Flow(树上差分)

    题目描述: Farmer John has installed a new system of N−1N-1N−1 pipes to transport milk between the NNN st ...

  7. P3128 [USACO15DEC]最大流Max Flow (树上差分)

    题目描述 Farmer John has installed a new system of N-1N−1 pipes to transport milk between the NN stalls ...

  8. 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status] ...

  9. 树上差分 (瞎bb) [树上差分][LCA]

    做noip2015的运输计划写了好久好久写不出来   QwQ 于是先来瞎bb一下树上差分    混积分 树上差分有2个常用的功能: (1)记录从点i到i的父亲这条路径走过几次 (2)将每条路径(s,t ...

随机推荐

  1. Docker 加速器设置

    在部署完docker的时候我们需要进行在镜像源下载镜像的时候有时候会出现特别慢的情况(这是因为本地到源的网络出现了问题),这时候就需要使用加速器来对镜像进行下载了,在面咱们就聊一聊docker加速器的 ...

  2. 云卡门禁安卓SDK_BLEDOOR_SDK_ANDROID_2016_12_15

    package com.bosk.bledoor.sdk; //sdk包的开门服务类,AndroidManifest.xml 必须注册 //<service //android:name=&qu ...

  3. JavaScript大杂烩17 - 性能优化

    在上一节推荐实践中其实很多方面是与效率有关的,但那些都是语言层次的优化,这一节偏重学习大的方面的优化,比如JavaScript脚本的组织,加载,压缩等等. 当然在此之前,分析一下浏览器的特征还是很有意 ...

  4. C# 异步编程4 async与await 异步程序开发

    随着C#异步程序开发系列的深入,你会发现编写异步程序越发简单.事物的发展就是这样的规律,从简单到复杂再到简单. 在C# 5.0中我们可以通过async与await关键字实现快捷的异步程序开发,如下: ...

  5. openldap系列

    openldap系列 阅读视图 系列介绍 openldap系列目录 1. 系列介绍 本系列文档大部分来自于郭大勇老师的<OpenLDAP实战指南>,少部分来自于互联网.所有文档均已经过本人 ...

  6. const int *p 和int * const p 的区别

    看例子: int sloth = 3; const int *p1 = &sloth; int * p2 const = &sloth; 这样申明的话,不允许使用p1来修改sloth的 ...

  7. MailKit帮助类

    public class EmailHelp { /// <summary> /// Smtp服务器地址 /// </summary> private static reado ...

  8. Oracle 单引号 双引号 转义符 分隔符

    概述 单引号用来标记字符串 双引号用来标记识别对象名 以下使用会比较绕: 字符串中出现单引号.双引号: 表或字段等对象的别名(alias)中出单引号.双引号: 单引号.双引号与空格一起使用: 双引号 ...

  9. Beta冲刺(4/5)(麻瓜制造者)

    今日已完成 邓弘立:完成了商品管理(下架)和搜索功能 符天愉:完成了后台管理员界面的登录和其他视图的载入 江郑:昨天来决定跨域执行请求,后台参考一些意见以后,操作起来没有那么容易实现,和队友交流以后本 ...

  10. Session共享的四种方法

    1. 基于NFS的Session共享 NFS是Net FileSystem的简称,最早由Sun公司为解决Unix网络主机间的目录共享而研发. 这个方案实现最为简单,无需做过多的二次开发,仅需将共享目录 ...