代码模板
今天有空来专门总结一下代码模版,顺便定制一张代码模版鼠标垫,哦吼!!!
↑这就是预期效果啦!!!
下面开始总结算法模版:
有关统一方面的算法过多时,会自动整理成一个专题放在这里:
最短路专题
素数筛(线性筛)
时间复杂度 \(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;
}