A_S の 模板库
目录
这里只存放还未深深刻在
DNA里的板子。板子可爱捏~
I 数据结构 & 树
0x10 树链剖分
0x11 LCA
0x12 LCT
0x13 splay & 平衡树
0x14 李超线段树
0x15 线段树
0x16 树状数组
0x17 可持久化线段树
0x18 可持久化01trie
0x19 分块
0x1A 单调栈
0x1B 树套树
II 动态规划
III 数学
0x30 线性基
IV 图论
0x40 最短路
SPFA
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std ;
const int N = 1e4+10 ;
const int M = 5e5+10 ;
struct Edge{
int to ,next ,w ;
}edge[M] ;
int head[N] ,edge_cnt ;
inline void edge_add(int from , int to , int w){edge[++edge_cnt] = {to,head[from],w} ;head[from] = edge_cnt ;}
int dis[N] ,vis[N] ,n ,m ,s ;
inline void spfa(){
memset(dis , 0x3f , sizeof dis) ;
queue<int> q ;
q.push(s) ;dis[s] = 0 ;
while(!q.empty()){
int u = q.front() ;q.pop() ;vis[u] = 0 ;
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].to ,w = edge[i].w ;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w ;
if(vis[v] == 0){
vis[v] = 1 ,q.push(v) ;
}
}
}
}
}
int main(){
ios::sync_with_stdio(0) ;
cin >> n >> m >> s ;
for(int i = 1,u,v,w;i <= m;++i){
cin >> u >> v >> w ;
edge_add(u , v , w) ;
}
spfa() ;
for(int i = 1;i <= n;++i) cout << (dis[i] == 0x3f3f3f3f ? (1<<31)-1 : dis[i]) << ' ' ;
return 0 ;
}
Dijkstra
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std ;
#define pii pair<int,int>
const int N = 1e5+10 ;
const int M = 2e5+10 ;
struct Edge{
int to ,next ,w ;
}edge[M] ;
int head[N] ,edge_cnt ;
inline void edge_add(int from , int to , int w){edge[++edge_cnt] = {to,head[from],w} ;head[from] = edge_cnt ;}
int dis[N] ,vis[N] ,n ,m ,s ;
priority_queue<pii> q ;
inline void dij(){
memset(dis , 0x3f , sizeof dis) ;
q.push({0,s}) ,dis[s] = 0 ;
while(!q.empty()){
int u = q.top().second ;q.pop() ;vis[u] = 0 ;
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].to ,w = edge[i].w ;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w ;
if(vis[v] == 0){
vis[v] = 1 ;
q.push({-dis[v] , v}) ;
}
}
}
}
}
int main(){
ios::sync_with_stdio(0) ;
cin >> n >> m >> s ;
for(int i = 1,u,v,w;i <= m;++i){
cin >> u >> v >> w ;
edge_add(u , v , w) ;
}
dij() ;
for(int i = 1;i <= n;++i) cout << dis[i] << ' ' ;
return 0 ;
}
判负环
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std ;
const int N = 1e4+10 ;
const int M = 5e5+10 ;
struct Edge{
int to ,next ,w ;
}edge[M<<1] ;
int head[N] ,edge_cnt ;
inline void edge_add(int from , int to , int w){edge[++edge_cnt] = {to,head[from],w} ,head[from] = edge_cnt ;}
bool vis[N] ;
int dis[N] ,len[N] ;
queue<int> q ;
int n ,m ;
inline void spfa(int s){
memset(dis , 0x7f , sizeof dis) ;memset(vis , 0 , sizeof vis) ;memset(len , 0 , sizeof len) ;
q.push(s) ;
dis[s] = 0 ;vis[s] = 1 ;len[s] = 0 ;
while(!q.empty()){
int node = q.front() ;q.pop() ;vis[node] = 0 ;
for(int i = head[node];i;i = edge[i].next){
int v = edge[i].to ,w = edge[i].w ;
if(dis[v] > dis[node] + w){
dis[v] = dis[node] + w ;
len[v] = len[node] + 1 ;
if(len[v] == n << 1){
cout << "YES\n" ;
return ;
}
if(vis[v] == 0) q.push(v) ,vis[v] = 1 ;
}
}
}
cout << "NO\n" ;
}
inline void solve(){
cin >> n >> m ;
memset(head , 0 , sizeof head) ;
edge_cnt = 0 ;
for(int i = 1;i <= m;++i){
int u ,v ,w ;cin >> u >> v >> w ;
edge_add(u , v , w) ;
if(w >= 0) edge_add(v , u , w) ;
}
spfa(1) ;
}
int main(){
ios::sync_with_stdio(0) ,cin.tie(0) ,cout.tie(0) ;
int t ;cin >> t ;
while(t--) solve() ;
return 0 ;
}
0x41 差分约束
注意转化方式。由于三角式松弛时是 \(dis_u+w\geqslant dis_v\),所以注意需要建立反向边。然后连边后求最短路是求得 \(x_i\leqslant 0\) 的所有 \(x_i\) 的最大解;求最长路是求得 \(x_i\geqslant 0\) 的所有 \(x_i\) 的最小解。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std ;
#define pii pair<int,int>
const int N = 5e3+10 ;
int n ,m ;
int dis[N] ,vis[N] ,len[N] ;
vector<pii> edge[N] ;
inline bool spfa(){
queue<int> q ;
for(int i = 1;i <= n;++i) vis[i] = 1 ,q.push(i) ;
while(!q.empty()){
int u = q.front() ;q.pop() ;
vis[u] = 0 ;
for(pii i : edge[u]){
int v = i.first ,w = i.second ;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w ;len[v] = len[u] + 1 ;
if(len[v] == n) return 1 ;
if(vis[v] == 0) vis[v] = 1 ,q.push(v) ;
}
}
}
return 0 ;
}
int main(){
ios::sync_with_stdio(0) ,cin.tie(0) ,cout.tie(0) ;
cin >> n >> m ;
for(int i = 1,u,v,w;i <= m;++i){
cin >> u >> v >> w ;
edge[v].push_back({u , w}) ;
}
if(spfa()){
cout << "NO" ;
return 0 ;
}
for(int i = 1;i <= n;++i) cout << dis[i] << ' ' ;
return 0 ;
}
0x42 最小生成树
Kruskal
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std ;
const int N = 5e3+10 ;
const int M = 2e5+10 ;
struct Edge{
int from ,to ,w ,next ;
}edge[M<<1] ;
int head[N] ,edge_cnt ;
int n ,m ,sum ,vis[N] ;
inline void edge_add(int from , int to , int w){edge[++edge_cnt] = {from,to,w,head[from]} ,head[from] = edge_cnt ;}
inline bool cmp(Edge a , Edge b){return a.w < b.w ;}
int fa[N] ;
inline int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]) ;}
int main(){
ios::sync_with_stdio(0) ,cin.tie(0) ,cout.tie(0) ;
cin >> n >> m ;for(int i = 1;i <= n;++i) fa[i] = i ;
for(int i = 1,u,v,w;i <= m;++i){
cin >> u >> v >> w ;
edge_add(u , v , w) ;//注意没有回边
}
sort(edge+1 , edge+1+m , cmp) ;
for(int i = 1;i <= m;++i){
int x = find(edge[i].from) ,y = find(edge[i].to) ;
if(x == y) continue ;
fa[x] = y ;
sum += edge[i].w ;
}
int cnt = 0 ;
for(int i = 1;i <= n;++i) if(fa[i] == i) cnt++ ;
if(cnt > 1){
cout << "orz" ;
return 0 ;
}
cout << sum ;
return 0 ;
}
Borvukal
blog
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define pii pair<int,int>
using namespace std ;
const int N = 5e3+10 ;
const int M = 2e5+10 ;
vector<pii> edge[N] ;
int fa[N] ,n ,m ,minn[2][N] ;
inline int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]) ;}
inline void merge(int x , int y){fa[find(x)] = find(y) ;}
int main(){
ios::sync_with_stdio(0) ,cin.tie(0) ,cout.tie(0) ;
cin >> n >> m ;
for(int i = 1,u,v,w;i <= m;++i){
cin >> u >> v >> w ;
edge[u].push_back({v , w}) ,edge[v].push_back({u,w}) ;
}
for(int i = 1;i <= n;++i) fa[i] = i ;
bool flag = 1 ;
int ans = 0 ;
while(flag){
memset(minn[0] , 0x3f , sizeof minn[0]) ;
flag = 0 ;
for(int u = 1;u <= n;++u)
for(pii i : edge[u]){
int v = i.first ,w = i.second ;
if(find(v) != find(u) && minn[0][find(u)] > w){
minn[0][find(u)] = w ;
minn[1][find(u)] = find(v) ;
}
}
for(int i = 1;i <= n;++i){
if(minn[0][i] != minn[0][0] && find(i) != find(minn[1][i])){
flag = 1 ;
ans += minn[0][i] ;
int x = find(i) ,y = find(minn[1][i]) ;
fa[x] = y ;
}
}
}
for(int i = 1;i < n;++i)
if(fa[i] != fa[i+1]){
cout << "orz" ;
return 0 ;
}
cout << ans ;
return 0 ;
}
V 多项式
VI 平面几何
VII 常见套路 & 模板组合
附录:待补充名单:
Johnson全源最短路

浙公网安备 33010602011771号