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全源最短路

posted @ 2023-07-31 18:33  adolf_stalin  阅读(13)  评论(0)    收藏  举报