B. 删边(cip.cpp/in/out 1S/256M)

题面

给出一个没有重边和自环的无向图,现在要求删除其中两条边,使得图仍然保持连通。

你的任务是计算有多少组不合法的选边方案。注意方案是无序二元组。

输入格式

第一行是两个整数 N 和 M,分别表示顶点数和边数

接下来 M 行,每行 2 个整数,表示一条无向边

输出格式

输出一行,表示对应的答案

输入样例

5 6

1 2

2 3

1 3

3 4

4 5

3 5

输出样例

6

数据规模

测试点 N M

10% 3000 7000

70% 50000 100000

100% 100000 300000

题解

首先,如果一条边是桥,那么另一条边任意;

对于非桥边:

构建DFS树。

显然,只有两种组合:树边+树边,树边+返祖边。

对每一条树边记录跨过它的返祖边集合 \(S\) ,返祖边跨过它的集合仅有它本身。

我们就会发现,任意两条非桥边同时删去可以使图不连通的充要条件是跨过他们的返祖边集合相同。

证明显然。

然后考虑如何表示一条边的返祖边集合:

利用哈希,给每条返祖边一个随机权值,加入哈希集合。

把边权变为点权。因为每条边有两个端点,考虑异或,给边的两个端点赋上这条边的权值。

树形dp,每个点异或它的所有儿子的权值,这样某条返祖边未覆盖的点就不会受到它的影响。将每个点的权值加入hash集合,表示这个点到它父亲的边。

哈希值有两种情况:

  1. hash==0 此时这条边为桥,ans+=边数
  2. hash!=0 求出每种哈希值的出现次数 \(m\) ,ans+=m*(m-1)/2

\(ans\) 即为答案。

ps1: 这样似乎可以推广到割k条边?

ps2: tarjan可以省了?

代码

放一下std:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#define SF scanf
#define PF printf
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 100000;
const int MAXM = 300000;
struct Node {
int v, next;
} Edge[MAXM*2+10];
int adj[MAXN+10], ecnt, n, m;
LL Hash[MAXN+10], ans;
bool vis[MAXN+10];
vector <pii> not_tree_edges;
vector <LL> Hash_set;
void addedge(int u, int v) {
Node &e = Edge[++ecnt];
e.v = v; e.next = adj[u]; adj[u] = ecnt;
}
void add(int u, int v) {
addedge(u, v); addedge(v, u);
}
void dfs(int u, int fa) {
vis[u] = true;
for(int i = adj[u]; i; i = Edge[i].next) {
int v = Edge[i].v;
if(!vis[v]) dfs(v, u);
else if(v != fa && v < u) not_tree_edges.push_back(make_pair(v, u));
}
}
LL Rand() {
LL x = 0;
for(int i = 0; i < 3; i++)
x = (x << 16) | rand();
return x;
}
void make_Hash() {
for(int i = 0; i < not_tree_edges.size(); i++) {
LL sta = Rand();
Hash[not_tree_edges[i].fir] ^= sta;
Hash[not_tree_edges[i].sec] ^= sta;
Hash_set.push_back(sta);
}
}
LL calc(int u) {
vis[u] = true;
for(int i = adj[u]; i; i = Edge[i].next) {
if(vis[Edge[i].v]) continue;
LL val = calc(Edge[i].v);
Hash[u] ^= val;
Hash_set.push_back(val);
}
return Hash[u];
}
void count_ans() {
sort(Hash_set.begin(), Hash_set.end());
int cnt = 0;
for(int i = 0; i < Hash_set.size(); i++)
if(!Hash_set[i])
cnt++;
ans += 1LL * cnt * (m - cnt);
for(int i = 0, j = 0; i < m; i = j) {
while(j < m && Hash_set[i] == Hash_set[j]) j++;
int del = j - i;
ans += 1LL * del * (del - 1) / 2;
}
}
int main() {
srand(19981103);
SF("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
SF("%d%d", &u, &v);
add(u, v);
}
dfs(1, 0);
memset(vis, 0, sizeof(vis));
make_Hash();
calc(1);
count_ans();
cout << ans;
}

[西安交大附中集训] d6 删边(cip)的更多相关文章

  1. [补档]暑假集训D6总结

    考试 不是爆零,胜似爆零= = 三道题,就拿了20分,根本没法玩好吧= = 本来以为打了道正解,打了道暴力,加上个特判分,应该不会死的太惨,然而--为啥我只有特判分啊- - 真的是惨. 讲完题觉得题是 ...

  2. [模板] 数位dp

    数位dp 简介 数位dp指满足特定性质的数的计数, 如求 \([l, r]\) 区间内不含 \(2\) 的数的个数. 一般来说, 数位dp利用dfs解决, 有时状态数较多, 需要hash表优化. 模板 ...

  3. [学习笔记]FWT——快速沃尔什变换

    解决涉及子集配凑的卷积问题 一.介绍 1.基本用法 FWT快速沃尔什变换学习笔记 就是解决一类问题: $f[k]=\sum_{i\oplus j=k}a[i]*b[j]$ 基本思想和FFT类似. 首先 ...

  4. 再探容斥好题——ROOK

    这个时候考过:安师大附中集训 Day2 当时看shadowice1984的做法,但是没有亲自写,,, 雅礼集训考试的时候鼓捣半天,被卡常到80pts,要跑9s 卡不动. 正解实际是: 3重容斥 1.随 ...

  5. TMOOC-1692-分西瓜

    题目 描述 今天是阴历七月初五,首师大附中信息社团队员GDC的生日.GDC正在和SCX.WXY在首师大附中集训.他想给这两位兄弟买点什么庆祝生日,经过调查,GDC发现SCX和WXY都很喜欢吃西瓜,而且 ...

  6. 删边(cip)

    删边(cip) 给出一个没有重边和自环的无向图,现在要求删除其中两条边,使得图仍然保持连通. 你的任务是计算有多少组不合法的选边方案.注意方案是无序二元组. Sol 神题,无从下手啊. 考虑点dfs建 ...

  7. [UOJ#268]. 【清华集训2016】数据交互[动态dp+可删堆维护最长链]

    题意 给出 \(n\) 个点的树,每个时刻可能出现一条路径 \(A_i\) 或者之前出现的某条路径 \(A_i\) 消失,每条路径有一个权值,求出在每个时刻过后能够找到的权值最大的路径(指所有和该路径 ...

  8. 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!

    前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...

  9. 2015UESTC 暑假集训总结

    day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...

随机推荐

  1. 基于vs2015的rdlc报表运行环境部署

    先说明一下,rdlc报表是由visual studio来支持的,不是FM. 本次项目采用的是vs2015开发的,当中使用了ReportViewer报表. 两种方式可以支持开发rdlc报表环境: 1)在 ...

  2. 面试 15:顺时针从外往里打印数字(剑指 Offer 第 20 题)

    面试 15:顺时针从外往里打印数字 题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印每一个数字.例如输入: {{1,2,3}, {4,5,6}, {7,8,9}} 则依次打印数字为 1.2.3. ...

  3. webpack 中版本兼容性问题错误总结

    一定不要运行npm i  XXX  -g(-d) 一定要指定版本,尽量低版本,也不最新版本,会导致不兼容和指令不一样的问题. 1.安装webpack-dev-server 报错,说需要webpack- ...

  4. 无法从带有索引像素格式的图像创建graphics对象

    大家在用 .NET 做图片水印功能的时候, 很可能会遇到 “无法从带有索引像素格式的图像创建graphics对象”这个错误,对应的英文错误提示是“A Graphics object cannot be ...

  5. Python2和Python3中urllib库中urlencode的使用注意事项

    前言 在Python中,我们通常使用urllib中的urlencode方法将字典编码,用于提交数据给url等操作,但是在Python2和Python3中urllib模块中所提供的urlencode的包 ...

  6. WebSocket实现一个聊天室

    聊天室页面-->index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...

  7. Jenkins deploy war to tomcat over https

    ssl - HTTPS login with Spring Security redirects to HTTP - Stack Overflow https://stackoverflow.com/ ...

  8. linux下编译upx ucl

    昨天,UPX发布了3.93版本. UPX(the Ultimate Packer for eXecutables)是一个非常全面的可执行文件压缩软件,支持dos/exe.dos/com.dos/sys ...

  9. mysql之找回误删数据

    场景:我们开发阶段,经常要有一些测试数据在我们测试相关功能的时候,是十分必要的.后期由于引入了正式的数据,但是测试数据并没有被及时清理.这个时候由于一个误删除,导致一些正式的数据被删除,由此,一场追找 ...

  10. anaconda + VSCode + 生产环境配置

    1. 修改jupyter notebook 默认路径: 进入anaconda 命令行, jupyter notebook --generate-config   生成配置文件, 该文件在    本机用 ...