代码模板

今天有空来专门总结一下代码模版,顺便定制一张代码模版鼠标垫,哦吼!!!

acwing算法鼠标垫

↑这就是预期效果啦!!!

下面开始总结算法模版:

有关统一方面的算法过多时,会自动整理成一个专题放在这里:

最短路专题

素数筛(线性筛)

时间复杂度 \(O(N)\)

void primes(int n){//线性筛区间[1,n]的素数 
	memset(isprime,true,sizeof(isprime));  //全部标记为素数 
    isprime[1]=false;m=0;
	for(int i=2;i<=n;i++){
		if(isprime[i]) prime[++m]=i;
		for(int j=1;j<=m;j++){
			if(prime[j]>n/i) break;//i*prime[j]超出n的范围 
			isprime[i*prime[j]]=false;
		    if(i%prime[j]==0) break;//保证prime[j]是i的最小质因子 
		}
	}
}

Tarjan求强联通分量

注意:要标记元素是否在栈内,有向图不用标记father

Tarjan强联通分量
void tarjan(int u){
	dfn[u]=low[u]=++tim;
	s.push(u);
	vis[u]=1;
	for(int e=fir[u];e;e=nex[e]){
		int v=to[e];
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]){
		cnt++;
		int v;
		do{
            v=s.top();s.pop();
			vis[v]=0;
			fl[v]=cnt;sl[cnt]++;
		}while(v!=u)
	}
}

LCA(最近公共祖先)

LCA倍增
void Init(int u,int father){
	dep[u]=dep[father]+1;
	for(int i=0;i<=16;i++)
		f[u][i+1]=f[f[u][i]][i];
	for(int e=first[u];e;e=Next[e]){
		int v=to[e];
		if(v==father) continue; 
		f[v][0]=u;   //v的父亲是u 
		Init(v,u); 
	}
}
int Lca(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);//保证x深度更大 
	for(int i=17;i>=0;i--){
		if(dep[f[x][i]]>=dep[y]) x=f[x][i];
		if(x==y) return x;  
	}
	for(int i=17;i>=0;i--){
		if(f[x][i]!=f[y][i]){ 
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];//最后跳到了lca的下面一个 
}
LCA(dfn序+RMQ)
#include<bits/stdc++.h>
using namespace std;
#define N 500005
int n,m,st,dft,dfn[N],mi[N][19];
vector<int>e[N];
int get(int x,int y){
	return dfn[x] < dfn[y] ? x : y;
}

void dfs(int u,int fa){
	dfn[u]=++dft;
	mi[dft][0]=fa;
	for(auto v:e[u]) if(v!=fa) dfs(v,u);
}

int lca(int u,int v){
	if(u==v) return u;
	u=dfn[u];v=dfn[v];
	if(u>v) swap(u,v);
	int d=__lg(v-u);
	return get(mi[u+1][d],mi[v-(1<<d)+1][d]);
}

int main(){
	scanf("%d%d%d",&n,&m,&st);
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(v);e[v].push_back(u);
	}
	dfs(st,0);
	for(int i=1;i<=__lg(n);i++){
		for(int j=1;j+(1<<i)-1<=n;j++){
			mi[j][i]=get(mi[j][i-1],mi[j+(1<<(i-1))][i-1]);
		}
	}
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		printf("%d\n",lca(u,v));
	}
}

树状数组

动态维护前缀和,支持单点,区间更新和查询

int lowbit(int i){
	return i & (-i);
}
void update(int j,int i){
	while(i<=n){
		tree[i]+=j;
		i+=lowbit(i);
	}
}
int query(int i){
	int sum=0;
	while(i>0){
		sum+=tree[i];
		i-=lowbit(i);
	}	
	return sum;
}

欧几里得(GCD)

int gcd(int a,int b){ //欧几里得(辗转相除) 
	if(b==0) return a;
	else return gcd(b,a%b);
}

快速幂

int fastpower(int a,int b){
	int ans=1;
	while(b>0){
		if(b&1) ans=(ans*a)%mod;
		b=b>>1;
		a=(a*a)%mod;
	}	
	return ans;
}

并查集

int getfather(int x){
	if(fa[x]==x) return x;
	fa[x]=getfather(fa[x]);
	return fa[x];
}
void merge(int x,int y){
	int fx=getfather(x);
	int fy=getfather(y);
	fa[fx]=fy;
}

KMP

void getNext() //计算Next数组
{
	int j=1,k=0;
	Next[1]=0;
	while(j<lent){
		if(k==0||t[j]==t[k])
			Next[++j]=++k;
		else k=Next[k];
	}
}

多次匹配

KMP多次匹配代码
#include<bits/stdc++.h>
using namespace std;
#define N 1000005
char s[N],t[N];
int nex[N],lens,lent;
int a[N],ans=0;

void getNext(){
	int j=1,k=0;
	nex[1]=0;
	while(j<lent){
		if(k==0||t[j]==t[k]){
			nex[++j]=++k;
		}
		else k=nex[k];
	}
}

int main(){
	scanf("%s",s+1);lens=strlen(s+1);
	scanf("%s",t+1);lent=strlen(t+1);
	getNext();
	int i=1,j=1;	
	while(i<=lens){
		if(j==0||s[i]==t[j]){
			i++,j++;
		}
		else{
			j=nex[j];
		}
		if(j>lent){
			j=1;
			a[++ans]=i-lent;
			i=i-lent+1;
		}
	}
	if(ans==0) printf("NO");
	for(int i=1;i<=ans;i++){
		printf("%d\n",a[i]);
	}
	return 0;
}

字典树(Trie)

字典树代码
#include<bits/stdc++.h>
using namespace std;
#define N 2000010
int tr[N][26],ed[N],tot,n,m;
char ch[N]; 

void build(){
	int u=0;
	for(int i=0;i<strlen(ch);i++){
		int c=ch[i]-'a';
		if(!tr[u][c]){
			tr[u][c]=++tot;
		}
		u=tr[u][c];
	}
	ed[u]++;
}

int query(){
	int u=0,ans=0;
	for(int i=0;i<strlen(ch);i++){
		int c=ch[i]-'a';
		if(!tr[u][c]) return ans;
		u=tr[u][c];
		ans+=ed[u];
	}
	return ans;
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%s",ch);
		build();
	}
	for(int i=1;i<=m;i++){
		scanf("%s",ch);
		printf("%d\n",query());
	}
	return 0;
}

哈希(hash)

单值哈希代码
#include<bits/stdc++.h>
using namespace std;
#define ULL unsigned long long
ULL a[10010];
int n;
const int base=131;

ULL hashes(char s[]){
	int len=strlen(s);
	ULL ans=0;
	for(int i=0;i<len;i++){
		ans=ans*base+s[i];
	}
	return ans;
} 

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		char s[20000];
		scanf("%s",s);
		a[i]=hashes(s);
	}
	sort(a+1,a+1+n);
	int ans=1;
	for(int i=2;i<=n;i++){
		if(a[i]!=a[i-1]) ans++;
	}
	printf("%llu\n",ans);
	return 0;
}

树的直径

树的直径代码
#include<bits/stdc++.h>
using namespace std;
#define N 200000
int fir[N],nex[N],to[N],tot,w[N];
int dep[N>>1],z1,z2,n;

void add(int x,int y,int z){
	nex[++tot]=fir[x];
	fir[x]=tot;
	to[tot]=y;
	w[tot]=z;
}

void dfs1(int u,int fa){
	for(int e=fir[u];e;e=nex[e]){
		int v=to[e];
		if(v==fa) continue;
		dep[v]=dep[u]+w[e];
		dfs1(v,u);
		if(dep[z1]<dep[v]) z1=v;
	}
}

void dfs2(int u,int fa){
	for(int e=fir[u];e;e=nex[e]){
		int v=to[e];
		if(v==fa) continue;
		dep[v]=dep[u]+w[e];
	//	printf("%d\n",u);
	//	printf("%d %d %d %d\n",v,dep[v],fa,dep[fa]);
		dfs2(v,u);
		if(dep[z2]<dep[v]) z2=v;
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	dep[1]=0;
	dfs1(1,0);
	memset(dep,0,sizeof(dep));
	dfs2(z1,0);
	printf("%d",dep[z2]);
	return 0;
}

树的重心

树的重心代码
#include<bits/stdc++.h>
using namespace std;
#define N 40010
int fir[N],to[N],nex[N],tot;
int n,f[N],size[N],z;

void add(int x,int y){
	nex[++tot]=fir[x];
	fir[x]=tot;
	to[tot]=y;
}

void dfs(int u,int fa){
	size[u]=1;
	for(int e=fir[u];e;e=nex[e]){
		int v=to[e];
		if(v==fa) continue;
		dfs(v,u);
		size[u]+=size[v];
		f[u]=max(f[u],size[v]);
	}
	f[u]=max(f[u],n-size[u]);
	if(f[u]==f[z]) z=min(z,u);
//	printf("%d %d\n",f[u],f[z]);
	if(f[u]<f[z]) z=u;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	z=0;
	f[z]=99999999;
	dfs(1,0);
	printf("%d %d",z,f[z]);
	return 0;
}

二分图匹配(匈牙利算法)

匈牙利算法(过山车)
#include<bits/stdc++.h>
using namespace std;
int match[505];
int used[505];
int k,m,n,x,y;
vector<int>e[1005];

bool dfs(int x){
	for(auto v:e[x]){
		if(!used[v]){
			used[v]=1;
			if(match[v]==0||dfs(match[v])){
				match[v]=x;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	while(scanf("%d",&k)!=EOF&&k){
		scanf("%d%d",&m,&n);
		for(int i=1;i<=k;i++){
			e[i].clear();
		}
		memset(match,0,sizeof(match));
		for(int i=1;i<=k;i++){
			scanf("%d%d",&x,&y);
			e[x].push_back(y);
		}
		int sum=0;
		for(int i=1;i<=m;i++){
			memset(used,0,sizeof(used));
			if(dfs(i)) sum++;
		}
		printf("%d",sum);
	}
	return 0;
}
posted @ 2023-10-07 19:53  alloverzyt  阅读(24)  评论(0编辑  收藏  举报