模板
最短路
【1】dijkstra
priority_queue<pair<int,int> >q; int d[maxn],vis[maxn]; void dijkstra() { memset(d,0x3f,sizeof(d)); memset(vis,0,sizeof(vis)); d[0]=0; q.push(make_pair(0,0)); while(!q.empty()){ int x=q.top().second;q.pop(); if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=edge[i].next){ int y=edge[i].to,v=edge[i].val; if(d[y]>d[x]+v){ d[y]=d[x]+v; q.push(make_pair(-d[y],y)); } } } }
【2】spfa
最小生成树
【1】prim
int prim(int x) { memset(vis,0,sizeof(vis)); memset(d,0x3f,sizeof(d)); int ans=0; d[1]=0; for(int i=1;i<=x;i++) { int t,m=1<<30; for(int j=1;j<=x;j++) if(!vis[j] && d[j]<m) { m=d[j]; t=j; } vis[t]=1;ans+=m; for(int j=1;j<=x;j++) if(!vis[j] && a[t][j]!=0) d[j]=min(d[j],a[t][j]); } return ans; }
【2】kruskal
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int maxn = 200000 + 10 ; struct Node{ int x,y,z; }edge[maxn]; int f[maxn]; bool cmp(Node a,Node b){return a.z<b.z;} int n,m,c,ans; int find(int x){return x==f[x]?x:f[x]=find(f[x]);} void kruskal() { int f1,f2,k(0); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { f1=find(edge[i].x);f2=find(edge[i].y); if(f1!=f2){ ans=ans+edge[i].z; f[f1]=f2; if(++k==n-1) break; } } if(k<n-1) c=1; } int main() { cin>>n>>m; for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z); sort(edge+1,edge+1+m,cmp); kruskal(); printf( c ? "orz\n" : "%d\n",ans); return 0; }
线段树
struct Node { int l,r; int maxx; }point[maxn * 4]; int x,y,a[maxn]; void Build_tree(int b,int l,int r) { point[b].l=l,point[b].r=r; if(l==r) point[b].maxx=a[l]; else { int mid = ( l + r ) / 2; Build_tree(b*2,l,mid); Build_tree(b*2+1,mid+1,r); point[b].maxx=max(point[2*b].maxx,point[b*2+1].maxx); } } int query(int b) { if(x<=point[b].l && y>=point[b].r) return point[b].maxx; int mid = ( point[b].l + point[b].r ) / 2; int ans = -(1<<30); if(mid>=x) ans=max(ans,query(b*2)); if(mid<y) ans=max(ans,query(b*2+1)); return ans; }
树状数组
lca
void Deal_first(int u,int fa) { Dep[u]=Dep[fa]+1; for(int i=0;i<=29;i++) f[u][i+1]=f[f[u][i]][i]; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; value[v]=value[u]+vi[i]; f[v][0]=u; Deal_first(v,u); } } int LCA(int x,int y) { if(Dep[x]<Dep[y]) swap(x,y); for(int i=30;i>=0;i--) { if(Dep[f[x][i]]>=Dep[y]) x=f[x][i]; if(x==y) return x; } for(int i=30;i>=0;i--) if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } return f[x][0]; }
树的直径
void dfs(int u,int fa) { for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; dfs(v,u); fir[u]=max(fir[u],fir[v]); fir[u]=max(fir[u],dwn[u]+dwn[v]+1); dwn[u]=max(dwn[u],dwn[v]+1); } }
tarjan强连通分量
int dfn[maxm],low[maxn],sccno[maxn],tim,ans[maxn]; int s[maxn],top,sec_cnt; void dfs(int u) { low[u]=dfn[u]=++tim; s[++top] = u; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(!dfn[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if(!sccno[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { sec_cnt++; for(;;) { int x= s[top--]; sccno[x] = sec_cnt; ans[sec_cnt]++; if(x==u) break; } } }
kmp
void kmp() { int j(0); for(int i=0;i<n;i++) { while(j>0 && B[j+1]!=A[i+1] ) j = p[j]; if(B[j+1]==A[i+1]) j++; if(j==m) { printf("%d\n",i+1-m+1); j=p[j]; } } } int main() { scanf("%s %s",A+1,B+1); p[1]=0; n=strlen(A+1),m=strlen(B+1); int j(0); p[1]=0; for(int i=1;i<m;i++) { while(j>0 && B[j+1]!=B[i+1]) j=p[j]; if(B[j+1]==B[i+1]) j++; p[i+1]=j; } kmp(); return 0; }
Trie字典树
Hash
树链剖分
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int maxn = 30000 + 10 ; struct Node { int next,to; }edge[maxn * 4]; int head[maxn * 4],num,power[maxn * 4],v[maxn * 4]; int f[maxn*4],size[maxn*4],deep[maxn * 4],son[maxn * 4],rk[maxn * 4],top[maxn * 4],id[maxn *4]; void add(int x,int y) { edge[++num].next=head[x]; head[x]=num; edge[num].to=y; } struct Tree { int left,right; int maxx,sum; }tree[maxn*4]; int n,q; void dfs1(int u,int fa) { size[u]=1; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; f[v]=u; deep[v]=deep[u]+1; dfs1(v,u); if(size[v]>size[son[u]]) son[u]=v; size[u]+=size[v]; } } int cnt; void dfs2(int u) { power[++cnt]=v[u]; // top[u]=t; id[u]=cnt; // rk[cnt]=u; if(u==son[f[u]]) top[u]=top[f[u]]; else top[u]=u; if(son[u]) dfs2(son[u]); for(int i=head[u];i;i=edge[i].next) { int v=edge[i].to; if(v!=son[u] && v!=f[u]) dfs2(v); } } void Build(int root,int left,int right) { tree[root].left=left; tree[root].right=right; if(left==right) {tree[root].sum=tree[root].maxx=power[left]; return;} int mid = (left+right)>>1; Build(root*2,left,mid); Build(root*2+1,mid+1,right); tree[root].sum=tree[root<<1].sum+tree[(root<<1)+1].sum; tree[root].maxx=max(tree[root<<1].maxx,tree[(root<<1)+1].maxx); } Tree query(int root,int left,int right) { if(left<=tree[root].left && right>=tree[root].right) return tree[root]; int mid = tree[root].left + tree[root].right >>1; if(mid>=right) return query(root<<1,left,right); else if(mid<left) return query((root<<1)+1,left,right); else { Tree ans,x=query(root<<1,left,mid),y=query((root<<1)+1,mid+1,right); ans.sum=x.sum+y.sum; ans.maxx=max(x.maxx,y.maxx); return ans; } } void modify(int pos,int x,int value) { if(tree[pos].left==tree[pos].right) tree[pos].sum=tree[pos].maxx=value; else{ int mid = (tree[pos].left+tree[pos].right)>>1; if(x<=mid) modify(pos*2,x,value); else modify(pos*2+1,x,value); tree[pos].sum=tree[pos*2+1].sum+tree[pos*2].sum; tree[pos].maxx=max(tree[pos*2+1].maxx,tree[pos*2].maxx); } } Tree sum(int x,int y) { Tree ans; ans.sum=0; ans.maxx=-12345678; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); Tree k=query(1,id[top[x]],id[x]); ans.sum+=k.sum; ans.maxx=max(ans.maxx,k.maxx); x=f[top[x]]; } if(deep[x]<deep[y]) swap(x,y); Tree k=query(1,id[y],id[x]); ans.sum+=k.sum; ans.maxx=max(ans.maxx,k.maxx); return ans; } int main() { cin>>n; for(int i=1,a,b;i<n;i++) { scanf("%d%d",&a,&b); add(a,b);add(b,a); } for(int i=1;i<=n;i++) cin>>v[i]; deep[1]=1; dfs1(1,0); dfs2(1);Build(1,1,cnt); cin>>q; while(q--) { int a,b;char c[20]; scanf("%s %d%d",c,&a,&b); if(c[1]=='M') printf("%d\n",sum(a,b).maxx); if(c[1]=='S') printf("%d\n",sum(a,b).sum); if(c[1]=='H') modify(1,id[a],b); } return 0; }
快速幂
int qpow(int a,int b) { long long sum(1); while(b){ if(b&1) sum=(long long)sum*a%mod; a=(long long)a*a%n; b>>=1; } return sum; }
逆元
二分图匈牙利算法
bool found(int x) { for(int i=1;i<=m;i++) if(map[x][i] && !used[i]) { used[i]=1; if(!lair[i] || found(lair[i])) { lair[i]=x; return true; } } return false; } int main()
{
for(int i=1;i<=n;i++) {
memset(used,0,sizeof(used));
if(found(i)) ans++;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步