[西安交大附中集训] d6 删边(cip)
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集合,表示这个点到它父亲的边。
哈希值有两种情况:
hash==0此时这条边为桥,ans+=边数;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)的更多相关文章
- [补档]暑假集训D6总结
考试 不是爆零,胜似爆零= = 三道题,就拿了20分,根本没法玩好吧= = 本来以为打了道正解,打了道暴力,加上个特判分,应该不会死的太惨,然而--为啥我只有特判分啊- - 真的是惨. 讲完题觉得题是 ...
- [模板] 数位dp
数位dp 简介 数位dp指满足特定性质的数的计数, 如求 \([l, r]\) 区间内不含 \(2\) 的数的个数. 一般来说, 数位dp利用dfs解决, 有时状态数较多, 需要hash表优化. 模板 ...
- [学习笔记]FWT——快速沃尔什变换
解决涉及子集配凑的卷积问题 一.介绍 1.基本用法 FWT快速沃尔什变换学习笔记 就是解决一类问题: $f[k]=\sum_{i\oplus j=k}a[i]*b[j]$ 基本思想和FFT类似. 首先 ...
- 再探容斥好题——ROOK
这个时候考过:安师大附中集训 Day2 当时看shadowice1984的做法,但是没有亲自写,,, 雅礼集训考试的时候鼓捣半天,被卡常到80pts,要跑9s 卡不动. 正解实际是: 3重容斥 1.随 ...
- TMOOC-1692-分西瓜
题目 描述 今天是阴历七月初五,首师大附中信息社团队员GDC的生日.GDC正在和SCX.WXY在首师大附中集训.他想给这两位兄弟买点什么庆祝生日,经过调查,GDC发现SCX和WXY都很喜欢吃西瓜,而且 ...
- 删边(cip)
删边(cip) 给出一个没有重边和自环的无向图,现在要求删除其中两条边,使得图仍然保持连通. 你的任务是计算有多少组不合法的选边方案.注意方案是无序二元组. Sol 神题,无从下手啊. 考虑点dfs建 ...
- [UOJ#268]. 【清华集训2016】数据交互[动态dp+可删堆维护最长链]
题意 给出 \(n\) 个点的树,每个时刻可能出现一条路径 \(A_i\) 或者之前出现的某条路径 \(A_i\) 消失,每条路径有一个权值,求出在每个时刻过后能够找到的权值最大的路径(指所有和该路径 ...
- 2017/10 冲刺NOIP集训记录:暁の水平线に胜利を刻むのです!
前几次集训都没有记录每天的点滴……感觉缺失了很多反思的机会. 这次就从今天开始吧!不能懈怠,稳步前进! 2017/10/1 今天上午进行了集训的第一次考试…… 但是这次考试似乎是近几次我考得最渣的一次 ...
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
随机推荐
- QQ的ldw值计算方法
- Clustering[Spectral Clustering]
0. 背景 谱聚类在2007年前后十分流行,因为它可以快速的通过标准的线性代数库来实现,且十分优于传统的聚类算法,如k-mean等. 至于在任何介绍谱聚类的算法原理上,随便翻开一个博客,都会有较为详细 ...
- Web登录其实没那么简单
1. 一个简单的HTML例子看看用户信息安全 标准的HTML语法中,支持在form表单中使用<input></input>标签来创建一个HTTP提交的属性,现代的WEB登录中, ...
- NLP是什么
NLP是什么 而在计算机领域, NLP(Natural Language Processing),也就是人们常说的「自然语言处理」,就是研究如何让计算机读懂人类语言. 这包括,既要能让计算机理解自然语 ...
- xadmin后台页面的自定制
01-自定制页面 注:最近找到了更好的解决办法:重写钩子函数版 https://www.cnblogs.com/pgxpython/p/10593507.html 需求背景:根据要实现的功能需求,x ...
- c++入门之文件读取
再次强调这个观念:写文件,读文件和读,写控制台本质上没有区别,意识到这一点是十分重要的.下面给出读文件的代码: #include "iostream" # include &quo ...
- myeclipse使用hibernate5框架load延迟装载对象报错_$$_javassist_0 cannot be cast to javassist.util.proxy.Proxy
jar包问题,将hibernate-core-5.0.12.Final.jar删除,换为hibernate-core-4.2.3.final.jar搞定.注意项目运行过后可能删不掉jar包,只需关闭m ...
- 把玩Alpine linux(一):安装
导读 Alpine Linux是一个面向安全应用的轻量级Linux发行版.它采用了musl libc和busybox以减小系统的体积和运行时资源消耗,同时还提供了自己的包管理工具apk.Alpine ...
- sql中return和returns的区别
用户定义函数中,用RETURNS 子句指定该函数返回值的数据类型 return用于返回具体的值/值变量
- PS调出水彩画效果古装人物照片
首先在PS里操作: 1.磨皮液化 磨皮液化就不细说啦~常规操作. 2.背景调色 分析:想塑造油画般的感觉,背景颜色想要蓝绿色 1.用可选颜色工具里面的中性色改变整体颜色,把皮肤和头发颜色用蒙版擦出来: ...