【bzoj5206】[Jsoi2017]原力 根号分治+STL-map
题目描述
输入
输出
输出一行一个整数,表示这个原力网络的总能量模10^9+7的值
样例输入
4 6
1 2 2 R
2 4 3 G
4 3 5 R
3 1 7 G
1 4 11 B
2 3 13 B
样例输出
828
题解
根号分治+STL-map
看到这种根本没法写出什么玄学数据结构之类的,大概率就是根号分治了。
对于本题,由于边数只有 $m$ ,因此度数大于等于 $\sqrt m$ 的点只有 $O(\sqrt m)$ 个,我们称这样的点为大点,度数小于 $\sqrt m$ 的称为小点。
那么对于一个三元环:
如果三个点都是大点:这种情况下我们暴力枚举三个大点,求出是否有满足条件的三元环并加入到答案中即可。时间复杂度为 $O((\sqrt m)^3)=O(m\sqrt m)$ ;
如果三个点中有小点:这种情况下我们枚举每个小点和它的两条出边,判断这三个点是否有满足条件的三元环。此时,枚举第一条出边相当于枚举图中所有边,第二条出边是度数复杂度,而度数小于 $\sqrt m$ ,因此复杂度也是 $O(m\sqrt m)$ 的。注意这个过程需要保证不重不漏,因此只考虑枚举点为这三个点中编号最小的小点的答案。
那么如何判断是否有满足条件的三元环呢?我偷懒了使用STL-map判断两点之间有没有某颜色的边,复杂度上会多一个log。
时间复杂度 $O(m\sqrt m\log m)$ ,实际上跑得挺快的 然而在bz上还是倒数第一...
#include <map>
#include <cmath>
#include <cstdio>
#define N 50010
#define mod 1000000007
using namespace std;
typedef long long ll;
struct data
{
int x , y , z;
data() {}
data(int a , int b , int c) {x = a , y = b , z = c;}
bool operator<(const data &a)const {return x == a.x ? y == a.y ? z < a.z : y < a.y : x < a.x;}
};
map<data , ll> mp;
int head[N] , to[N << 2] , val[N << 2] , opt[N << 2] , next[N << 2] , cnt , d[N] , id[350] , tot;
char str[5];
inline void add(int x , int y , int v , int c)
{
to[++cnt] = y , val[cnt] = v , opt[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
int n , m , si , i , j , k , x , y , z , t;
ll ans = 0;
scanf("%d%d" , &n , &m) , si = (int)sqrt(m);
for(i = 1 ; i <= m ; i ++ )
{
scanf("%d%d%d%s" , &x , &y , &z , str);
t = (str[0] == 'R' ? 1 : str[0] == 'G' ? 2 : 3);
add(x , y , z , t) , add(y , x , z , t) , d[x] ++ , d[y] ++ ;
(mp[data(x , y , t)] += z) %= mod , (mp[data(y , x , t)] += z) %= mod;
}
for(i = 1 ; i <= n ; i ++ )
if(d[i] >= si)
id[++tot] = i;
for(i = 1 ; i <= tot ; i ++ )
for(j = 1 ; j <= tot ; j ++ )
for(k = 1 ; k <= tot ; k ++ )
ans = (ans + mp[data(id[i] , id[j] , 1)] * mp[data(id[i] , id[k] , 2)] % mod * mp[data(id[j] , id[k] , 3)]) % mod;
for(i = 1 ; i <= n ; i ++ )
if(d[i] < si)
for(j = head[i] ; j ; j = next[j])
if(d[to[j]] >= si || to[j] > i)
for(k = next[j] ; k ; k = next[k])
if(opt[k] != opt[j] && (d[to[k]] >= si || to[k] > i))
ans = (ans + mp[data(to[j] , to[k] , 6 - opt[j] - opt[k])] * val[j] % mod * val[k]) % mod;
printf("%lld\n" , ans);
return 0;
}
【bzoj5206】[Jsoi2017]原力 根号分治+STL-map的更多相关文章
- BZOJ5206 [Jsoi2017]原力[根号分治]
这是一个三元环计数的裸题,只是多了一个颜色的区分和权值的计算罢了. 有一种根号分治的做法(by gxz) 这种复杂度的证明特别显然,思路非常简单,不过带一个log,可以用unordered_map或者 ...
- BZOJ5206: [Jsoi2017]原力
BZOJ5206: [Jsoi2017]原力 https://lydsy.com/JudgeOnline/problem.php?id=5206 分析: 比较厉害的三元环问题. 设立阈值,当点的度数大 ...
- BZOJ5206 JSOI2017原力(三元环计数)
首先将完全相同的边的权值累加.考虑这样一种trick:给边确定一个方向,由度数小的连向度数大的,若度数相同则由编号小的连向编号大的.这样显然会得到一个DAG.那么原图的三元环中就一定有且仅有一个点有两 ...
- [JSOI2017]原力(分块+map(hash))
题目描述 一个原力网络可以看成是一个可能存在重边但没有自环的无向图.每条边有一种属性和一个权值.属性可能是R.G.B三种当中的一种,代表这条边上 原力的类型.权值是一个正整数,代表这条边上的原力强度. ...
- bzoj 5206 [Jsoi2017]原力
LINK:原力 一张无向图 这道题统计三元环的价值和.有重边但是无自环. 我曾经写过三元环计数 这个和那个题差不太多. 不过有很多额外操作 对于重边问题 我们把所有颜色相同的重边缩在一起 这样的话我们 ...
- [JSOI2017]原力
题目大意: 一个$n(n\le5\times10^4)$个点,$m(m\le10^5)$条边的无向图.每条边有一个边权$w_i(w_i\le10^6)$和一个附加属性$t_i(t_i\in\{R,G, ...
- nowcoder 79F 小H和圣诞树 换根 DP + 根号分治
设节点个数大于 $\sqrt n$ 的颜色为关键颜色,那么可以证明关键颜色最多有 $\sqrt n$ 个.对于每个关键颜色,暴力预处理出该颜色到查询中另一个颜色的距离和. 对于不是关键颜色的询问,直接 ...
- (转载)STL map与Boost unordered_map的比较
原链接:传送门 今天看到 boost::unordered_map,它与 stl::map的区别就是,stl::map是按照operator<比较判断元素是否相同,以及比较元素的大小,然后选择合 ...
- CF804D Expected diameter of a tree 树的直径 根号分治
LINK:Expected diameter of a tree 1e5 带根号log 竟然能跑过! 容易想到每次连接两个联通快 快速求出直径 其实是 \(max(D1,D2,f_x+f_y+1)\) ...
随机推荐
- hasOwnProperty()函数
hasOwnProperty()函数的返回值为Boolean类型.如果对象object具有名称为propertyName的属性,则返回true,否则返回false 例子: function Site( ...
- 数据结构思维导图 Part1
刚刚结束数据结构的学习,在复习阶段,所以做来思维导图总结一下. 思维导图,顾名思义是应该有对思维有引导作用的,就像思维的整理术,然而想要学好什么,光看思维导图总是不够的. 树与图作为两个复杂非线性结构 ...
- Awesome TensorFlow
Awesome TensorFlow A curated list of awesome TensorFlow experiments, libraries, and projects. Inspi ...
- 九、Django之ORM
一.ORM概述 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 到目前为止,当我们的程序涉及到数据库相关操作时,一般操作流 ...
- Android开发笔记——视频录制播放常见问题
本文分享自己在视频录制播放过程中遇到的一些问题,主要包括: 视频录制流程 视频预览及SurfaceHolder 视频清晰度及文件大小 视频文件旋转 一.视频录制流程 以微信为例,其录制触发为按下(住) ...
- Python中print函数中中逗号和加号的区别
strip()方法,去除字符串开头或者结尾的空格 s = " a b c " new_s = s.strip() print("-------->%s<--- ...
- robotframework 脚本编写规范
测试集.脚本 测试脚本的名字不要超过20个字符,文件类型应该为txt 名字必需易读且有意义(看名知意) 记住测试集的名字是自动根据文件.目录的名字创建的.后缀名会被截去,下划线会转换为空格,如果名 ...
- katalon系列十三:5.10新增跳过用例&命令行赋值全局变量
Katalon Studio升级到5.10版本了,这次新增了2个很实用的功能:一.跳过用例在Listener中新增了跳过用例方法,Listener类似于JUnit4的annotation中的@Befo ...
- Linux中如何安装Apache服务器
Linux中如何安装Apache服务器 由于学习的需要,所有手动安装了一下Apache源码包,安装过程中的问题千奇百怪,但是如果弄清楚了问题出在哪里,那么也不是太难.如果有学习者出现安装中的问题,可仔 ...
- fiddler的断点使用
功能 用于修改数据 1.断点设置请求之前--修改请求数据 2.断点设置在响应时--对响应的数据修改 已中断的会话最前面的图标为红色的带箭头的标志 设置断点方法 1.菜单栏:rules->auto ...