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. ASP.NET Core如何使用WSFederation身份认证集成ADFS

    如果要在ASP.NET Core项目中使用WSFederation身份认证,首先需要在项目中引入NuGet包: Microsoft.AspNetCore.Authentication.WsFedera ...

  2. C# 设置最顶层窗口。TopMostWindow

    code: namespace LOLMM { /// <summary> /// Interaction logic for MainWindow.xaml /// </summa ...

  3. jsp相关基础知识

    一.JSP简介 JSP全称是Java Server Page,它和Servlet一样,也是sun公司推出的一套开发动态web资源的技术,称为JSP/Servlet规范.其本质也是一个Servlet. ...

  4. 性能调优8:分组聚合 - group by

    聚合实际上对数据做分组统计,SQL Server使用两种操作符来实现聚合,流聚合(Stream Aggregation)和哈希聚合(Hash aggration).流聚合是非阻塞性的,具有流的特性,流 ...

  5. CentOS 6 升级 curl

    zabbix 发邮件报 Support for SMTP authentication was not compiled in 其实出现这种问题的原因是我们机器上的 libcurl 版本太低所致.在z ...

  6. vue 生产环境 background 背景图不显示原因

    通常我们使用img标签引入文件,npm run build 打包后 ,因为img为html标签,打包后他的路径是由index.html开始访问的,他走static/img/'图片名'是能正确访问到图片 ...

  7. MYSQL中SUM (IF())

    今天一个朋友突然给我发过来一个sql语句,一下子问住我了. 我想,这种语法木有见过呀.我就查了查,才明白什么意思,原来是mysql里面的用法. SUM(IF(`hosts`.state = 0, 1, ...

  8. 【学习总结】GirlsInAI ML-diary day-4:变量/Variable

    [学习总结]GirlsInAI ML-diary 总 原博github链接-day4 变量/Variable 变量是计算机编程中一个很基础的概念,在计算机程序中,variables are reser ...

  9. 【问题解决方案】editplus中批量将ANSI转换为utf-8

    来自一个用editplus写java程序但是上传到GitHub里中文乱码的故事 大致步骤: editplus全部打开之后(打开为何种编码不重要): (全部打开是指在左下方的文件列表选中-->右击 ...

  10. vue路由动态过渡效果

    不多说,直接上代码 import Vue from 'vue' //引入vue import VueRouter from 'vue-router' //引入路由 Vue.use(VueRouter) ...