[Dr.Lib]Note:Algorithm – SSSP

最短路是图论中的基础,单源最短路SSSP是基础的基础(2333自己发明的名言……

关于图论算法之前只说了存图……唔今天先复习一下SSSP的几个算法。

Dijkstra

 SPFA

SPFA不仅是SSSP的一个算法,而更多的是一种思想。

国家集训队2009论文集SPFA算法的优化及应用

[Dr.Lib]Note:Data Structures – 关于存图

想当年,我只会用邻接矩阵,MLE的感人肺腑啊!

看最短路算法时,很多遍历边的方法我都看不懂。于是专门刷了一下存图……在此做个回顾总结。

部分来源于NOCOW。在此感谢。

邻接矩阵

作为图的一种储存方式,实际上就是一个二维数组。即为记为map[i][j],map[i][j]为节点i到节点j之间的边的权值,若不存在边,则为-1或其他。

这种储存方式的优势是书写方便,但缺点是非稠密图空间效率不高。相比之下,稍微麻烦点的前向星,邻接表等结构更加快速。

邻接表

邻接表是图的一种链式存储结构,在邻接表中,对图中每个顶点建立一个单链表,n个顶点,就要建n个链表。

第i个单链表中的结点表示依赖于顶点vi的边。单链表中每一个结点称为表结点,应包括三个域邻接点域、链域和数据域。邻接点域,用以存放与vi相邻接的顶点序号;链域用以指向与vi邻接的下一个结点,数据域存储和边或弧有关的的信息。

但是,为什么一定要链表呢?

有vector为什么不用呢?

前向星

前向星构造方法如下:

读入每条边的信息

将边存放在数组中

把数组中的边按照起点顺序排序

链式前向星

嗯,排序,快排,nlogn。

你看看人家存边只要O(n)……(如果你会计数排序的话……也行

那么……链式前向星。

还有吗……

十字链表和邻接多重表……在OI中还真没怎么见过

[Dr.Lib]Note:Data Structures – C++ STL

本着不重新发明轮子的原则,我很少手码快排和其他数据结构……基本都是拖STL出来用……

STL中还是有不少实用的数据结构的……set,bitset,priority_queue,queue,vector,map……

bitset

Via http://www.cplusplus.com/reference/bitset/bitset/

Member functions

(constructor)
Construct bitset (public member function )
applicable operators
Bitset operators (function )

 

Bit access

operator[]
Access bit (public member function )
count
Count bits set (public member function )
size
Return size (public member function )
test
Return bit value (public member function )
any
Test if any bit is set (public member function )
none
Test if no bit is set (public member function )
all 
Test if all bits are set (public member function )

 

Bit operations

set
Set bits (public member function )
reset
Reset bits (public member function )
flip
Flip bits (public member function )

 

Bitset operations

to_string
Convert to string (public member function )
to_ulong
Convert to unsigned long integer (public member function )
to_ullong 
Convert to unsigned long long (public member function )

在一些模拟中……bitset还是不错的……不过用处也不是很大……

priority_queue

Member functions

(constructor)
Construct priority queue (public member function )
empty
Test whether container is empty (public member function )
size
Return size (public member function )
top
Access top element (public member function )
push
Insert element (public member function )
emplace 
Construct and insert element (public member function )
pop
Remove top element (public member function )
swap 
Swap contents (public member function )

优先队列的用处就比较多了,据说优先队列优化dij秒爆SPFA[来源请求]……

只要定义了 operator< ,就可以用优先队列来做成大顶堆。小顶堆……要么改operator<,要么

priority_queue<T, vector<T>, greater<T> >

queue

Member functions

(constructor)
Construct queue (public member function )
empty
Test whether container is empty (public member function )
size
Return size (public member function )
front
Access next element (public member function )
back
Access last element (public member function )
push
Insert element (public member function )
emplace 
Construct and insert element (public member function )
pop
Remove next element (public member function )
swap 
Swap contents (public member function )

有优先队列优化的dij,就有队列优化的Bellman-Ford……

vector

Member functions

(constructor)
Construct vector (public member function )
(destructor)
Vector destructor (public member function )
operator=
Assign content (public member function )

Iterators:

begin
Return iterator to beginning (public member function )
end
Return iterator to end (public member function )
rbegin
Return reverse iterator to reverse beginning (public member function )
rend
Return reverse iterator to reverse end (public member function )
cbegin 
Return const_iterator to beginning (public member function )
cend 
Return const_iterator to end (public member function )
crbegin 
Return const_reverse_iterator to reverse beginning (public member function )
crend 
Return const_reverse_iterator to reverse end (public member function )

Capacity:

size
Return size (public member function )
max_size
Return maximum size (public member function )
resize
Change size (public member function )
capacity
Return size of allocated storage capacity (public member function )
empty
Test whether vector is empty (public member function )
reserve
Request a change in capacity (public member function )
shrink_to_fit 
Shrink to fit (public member function )

Element access:

operator[]
Access element (public member function )
at
Access element (public member function )
front
Access first element (public member function )
back
Access last element (public member function )
data 
Access data (public member function )

Modifiers:

assign
Assign vector content (public member function )
push_back
Add element at the end (public member function )
pop_back
Delete last element (public member function )
insert
Insert elements (public member function )
erase
Erase elements (public member function )
swap
Swap content (public member function )
clear
Clear content (public member function )
emplace 
Construct and insert element (public member function )
emplace_back 
Construct and insert element at the end (public member function )

Allocator:

get_allocator
Get allocator (public member function )

vector是个好东西,妈妈再也不用担心我的内存!

数组开大了爆内存,开小了爆下标……WTF……

还用的着担心邻接表MLE?vector没有压力。

map

Member functions

(constructor)
Construct multimap (public member function )
(destructor)
Multimap destructor (public member function )
operator=
Copy container content (public member function )

Iterators:

begin
Return iterator to beginning (public member function )
end
Return iterator to end (public member function )
rbegin
Return reverse iterator to reverse beginning (public member function )
rend
Return reverse iterator to reverse end (public member function )
cbegin 
Return const_iterator to beginning (public member function )
cend 
Return const_iterator to end (public member function )
crbegin 
Return const_reverse_iterator to reverse beginning (public member function )
crend 
Return const_reverse_iterator to reverse end (public member function )

Capacity:

empty
Test whether container is empty (public member function )
size
Return container size (public member function )
max_size
Return maximum size (public member function )

Modifiers:

insert
Insert element (public member function )
erase
Erase elements (public member function )
swap
Swap content (public member function )
clear
Clear content (public member function )
emplace 
Construct and insert element (public member function )
emplace_hint 
Construct and insert element with hint (public member function )

Observers:

key_comp
Return key comparison object (public member function )
value_comp
Return value comparison object (public member function )

Operations:

find
Get iterator to element (public member function )
count
Count elements with a specific key (public member function )
lower_bound
Return iterator to lower bound (public member function )
upper_bound
Return iterator to upper bound (public member function )
equal_range
Get range of equal elements (public member function )

Allocator:

get_allocator
Get allocator (public member function )

map用在一些需要存储键值对的地方……在一些需要维护数据的地方用这个偷懒一下也不错……

别忘了multimap。

 

[Dr.Lib]Note:Data Structures – 数据结构那些事

树状数组

[Dr.Lib]Note:Algorithms – 树状数组
树状数组是个简单高效的数据结构,实质上是省掉一半空间后的线段树加上中序遍历{Via ZKW《统计的力量》}

一般情况下,他可以做到单点更新,区间求和。

 http://wikioi.com/problem/1080/

小小的差分一下,就可以做到区间更新单点值

http://wikioi.com/problem/1081/

问题是区间更新区间和呢?

只能上线段树了吗?

NO!

http://wikioi.com/problem/1082/

朴素线段树

[Dr.Lib]Note:Algorithms – 线段树

*计算几何在长期的发展中,
诞生了许多实用的数据结构。
*区间查询,穿刺查询都是计算几何解决的问题
*作为特例中的特例,线段树解决的问题是:
*一维空间上的几何统计
 Via 《统计的力量》

线段树(Segment Tree)是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

对于线段树中的每一个非叶子节点[a,b],它的左子树表示的区间为[a,(a+b)/2],右子树表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树。叶节点数目为N,即整个线段区间的长度。

http://wikioi.com/problem/1191

ZKW线段树

参见《统计的力量》

 

 

[Dr.Lib]Note:Math – 欧拉函数

正在纠结要不要码一篇欧拉函数……IvyEnd神犇的大作就已经出炉了……

Via http://www.ivy-end.com/archives/1021

欧拉函数\(\varphi \left ( N \right )\)表示小于或等于\(N\)的正整数中与\(N\)互质的数的个数。又称\(\varphi\)函数、欧拉商数。

下面介绍欧拉函数的几个性质:

  • \(\displaystyle\varphi\left ( 1 \right )=1\)。
  • \(\displaystyle\varphi \left( N\right )=N\cdot\prod_{p\mid N}\left ( \frac{p-1}{p} \right )\)。
  • \(\displaystyle\varphi \left ( p^{k} \right ) = p^{k}-p^{k-1}=\left(p-1 \right )\cdot p^{k-1}\),其中\(p\)为质数。
  • \(\displaystyle\varphi \left(mn \right )=\varphi \left(m \right )\cdot \varphi \left(n \right )\),其中\(\gcd \left ( m,n \right )=1\)。

我们根据这几个性质就可以求出欧拉函数。

基本思路是首先置\(\varphi \left ( N \right )=N\),然后再枚举素数\(p\),将\(p\)的整数倍的欧拉函数\(\varphi \left ( kp \right )\)进行操作\(\varphi \left ( kp \right )=\varphi \left ( kp \right )\cdot \frac{p-1}{p}\)即可。

以及求单点的函数值

应用:

欧拉定理

\(a^{\varphi(n)}=1 \mod {n}\)

 

原根个数

\(\varphi \left ( \varphi \left ( N \right ) \right )\)

对于原根的定义,我们可以这样来叙述:

若存在一个实数\(a\),使得\(a^{i}\mod{N},a\in\left \{ 1,2,3,\cdots ,N \right \}\)的结果各不相同,我们就成实数\(a\)为\(N\)的一个原根。

原根的个数等于\(\varphi \left ( \varphi \left ( N \right ) \right )\)。这样我们就可以很方便的求出原根的个数。(参考题目

指数循环节

Via http://hi.baidu.com/aekdycoin/item/e493adc9a7c0870bad092fd9

\( A^{x}=A^{x\%\varphi(C) + \varphi(C)} \mod{C} (x \ge \varphi(C))\)