链式前向星
struct edge{
int v,w,nxt;
}e[m+5];
int head[n+5],cnt=1;
void add(int u,int v,int w){
cnt++,e[cnt].v=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;
}
for(int i=head[now];i;i=e[i].nxt)//do something
强连通分量(tarjan)
int dfn[n+5],low[n+5],st[n+5],top,ans,d;
bool vis[n+5];
void dfs(int pos,vector<int>e[],vector<int>scc[],int num[]){
low[pos]=dfn[pos]=++d,st[++top]=pos,vis[pos]=1;
for(int i=0;i<e[pos].size();i++){
if(!dfn[e[pos][i]])dfs(e[pos][i],e,scc,num),low[pos]=min(low[pos],low[e[pos][i]]);
else if(vis[e[pos][i]])low[pos]=min(low[pos],dfn[e[pos][i]]);
}
if(dfn[pos]==low[pos]){
ans++;
do scc[ans].push_back(st[top]),num[st[top]]=ans,vis[st[top]]=0;
while(st[top--]!=pos);
}
}
int tarjan(int n,vector<int>e[],vector<int>scc[],int num[]){
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,e,scc,num);
return ans;
}
强连通分量(kosaraju)
int st[n+5],top,ans;
bool vis[n+5];
vector<int>g[n+5];
void dfs1(int pos,vector<int>e[]){
vis[pos]=1;
for(int i=0;i<e[pos].size();i++)if(!vis[e[pos][i]])dfs1(e[pos][i],e);
st[++top]=pos;
}
void dfs2(int pos,vector<int>g[],vector<int>scc[],int num[]){
num[pos]=ans,scc[ans].push_back(pos);
for(int i=0;i<g[pos].size();i++)if(!num[g[pos][i]])dfs2(g[pos][i],g,scc,num);
}
int kosaraju(int n,vector<int>e[],vector<int>scc[],int num[]){
for(int i=1;i<=n;i++)for(int j=0;j<e[i].size();j++)g[e[i][j]].push_back(i);
for(int i=1;i<=n;i++)if(!vis[i])dfs1(i,e);
for(int i=top;i>=1;i--)if(!num[st[i]])ans++,dfs2(st[i],g,scc,num);
return ans;
}
割点
int dfn[n+5],low[n+5],ans,d;
void dfs(int pos,bool f,vector<int>e[],int c[]){
int num=0;
low[pos]=dfn[pos]=++d;
for(int i=0;i<e[pos].size();i++){
if(!dfn[e[pos][i]])dfs(e[pos][i],0,e,c),low[pos]=min(low[pos],low[e[pos][i]]),num+=low[e[pos][i]]>=dfn[pos];
else low[pos]=min(low[pos],dfn[e[pos][i]]);
}
if(num>f)c[++ans]=pos;
}
int tarjan(int n,vector<int>e[],int c[]){
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,1,e,c);
return ans;
}
割边
int dfn[n+5],low[n+5],ans,d;
void dfs(int pos,int p,edge e[],int head[],int c[]){
low[pos]=dfn[pos]=++d;
for(int i=head[pos];i;i=e[i].nxt){
if(!dfn[e[i].v]){
dfs(e[i].v,i,e,head,c),low[pos]=min(low[pos],low[e[i].v]);
if(low[e[i].v]>dfn[pos])c[++ans]=i;
}
else if(i!=(p^1))low[pos]=min(low[pos],dfn[e[i].v]);
}
}
int tarjan(int n,edge e[],int head[],int c[]){
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,0,e,head,c);
return ans;
}
点双连通分量
int dfn[n+5],low[n+5],st[n+5],top,ans,d;
void dfs(int pos,vector<int>e[],vector<int>dcc[]){
low[pos]=dfn[pos]=++d,st[++top]=pos;
if(!e[pos].size()){
dcc[++ans].push_back(pos);
return;
}
for(int i=0;i<e[pos].size();i++){
if(!dfn[e[pos][i]]){
dfs(e[pos][i],e,dcc),low[pos]=min(low[pos],low[e[pos][i]]);
if(low[e[pos][i]]>=dfn[pos]){
dcc[++ans].push_back(pos);
while(st[top+1]!=e[pos][i])dcc[ans].push_back(st[top--]);
}
}
else low[pos]=min(low[pos],dfn[e[pos][i]]);
}
}
int tarjan(int n,vector<int>e[],vector<int>dcc[]){
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,e,dcc);
return ans;
}
边双连通分量
int dfn[n+5],low[n+5],ans,d;
bool c[m+5];
void dfs1(int pos,int p,edge e[],int head[]){
low[pos]=dfn[pos]=++d;
for(int i=head[pos];i;i=e[i].nxt){
if(!dfn[e[i].v]){
dfs1(e[i].v,i,e,head),low[pos]=min(low[pos],low[e[i].v]);
if(low[e[i].v]>dfn[pos])c[i]=c[i^1]=1;
}
else if(i!=(p^1))low[pos]=min(low[pos],dfn[e[i].v]);
}
}
void dfs2(int pos,edge e[],int head[],vector<int>dcc[],int num[]){
dcc[ans].push_back(pos),num[pos]=ans;
for(int i=head[pos];i;i=e[i].nxt)if(!num[e[i].v]&&!c[i])dfs2(e[i].v,e,head,dcc,num);
}
int tarjan(int n,edge e[],int head[],vector<int>dcc[],int num[]){
for(int i=1;i<=n;i++)if(!dfn[i])dfs1(i,0,e,head);
for(int i=1;i<=n;i++)if(!num[i])ans++,dfs2(i,e,head,dcc,num);
return ans;
}
Prim堆优化
long long dis[n+5];
bool vis[n+5];
priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>>q;
long long prim(int n,vector<pair<int,long long>>e[],int cnt=0,long long ans=0){
for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f3f3f3f3f;
dis[1]=0,q.push(make_pair(0,1));
while(!q.empty()){
int now=q.top().second;
q.pop();
if(vis[now])continue;
vis[now]=1,cnt++,ans+=dis[now];
for(int i=0;i<e[now].size();i++){
int v=e[now][i].first;
long long w=e[now][i].second;
if(dis[v]>w)dis[v]=w,q.push(make_pair(dis[v],v));
}
}
return cnt==n?ans:-1;
}
Kruskal
struct edge{
int u,v;
long long w;
};
bool operator<(const edge &a,const edge &b){
return a.w<b.w;
}
DSU<n+5>a;
long long kruskal(int n,int m,edge e[],long long ans=0,int cnt=0){
a.build(n),sort(e+1,e+m+1);
for(int i=1;i<=m;i++)if(a.merge(e[i].u,e[i].v))ans+=e[i].w,cnt++;
return cnt==n-1?ans:-1;
}
Dijkstra
bool vis[n+5];
void dijkstra(int st,int n,vector<pair<int,long long>>e[],long long dis[]){
for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f3f3f3f3f;
dis[st]=0;
while(1){
int now=0;
for(int i=1;i<=n;i++)if(!vis[i]&&dis[now]>dis[i])now=i;
if(!now)break;
vis[now]=1;
for(int i=0;i<e[now].size();i++)dis[e[now][i].first]=min(dis[e[now][i].first],dis[now]+e[now][i].second);
}
}
Dijkstra堆优化
bool vis[n+5];
priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>>q;
void dijkstra(int st,int n,vector<pair<int,long long>>e[],long long dis[]){
for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f3f3f3f3f;
dis[st]=0,q.push(make_pair(0,st));
while(!q.empty()){
int now=q.top().second;
q.pop();
if(vis[now])continue;
vis[now]=1;
for(int i=0;i<e[now].size();i++){
int v=e[now][i].first;
long long w=e[now][i].second;
if(dis[v]>dis[now]+w)dis[v]=dis[now]+w,q.push(make_pair(dis[v],v));
}
}
}
spfa
bool vis[n+5];
int cnt[n+5];
queue<int>q;
bool spfa(int st,int n,vector<pair<int,long long>>e[],long long dis[]){
for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f3f3f3f3f;
dis[st]=0,q.push(st),vis[st]=1,cnt[st]++;
while(!q.empty()){
int now=q.front();
vis[now]=0,q.pop();
for(int i=0;i<e[now].size();i++){
int v=e[now][i].first;
long long w=e[now][i].second;
if(dis[v]>dis[now]+w){
dis[v]=dis[now]+w;
if(!vis[v]){
vis[v]=1,q.push(v),cnt[v]++;
if(cnt[v]>=n)return 1;
}
}
}
}
return 0;
}
拓扑排序
int deg[n+5];
queue<int>q;
void topsort(int n,vector<int>e[]){
for(int i=1;i<=n;i++)for(int j=0;j<e[i].size();j++)deg[e[i][j]]++;
for(int i=1;i<=n;i++)if(!deg[i])q.push(i);
while(!q.empty()){
int now=q.front();
q.pop()
for(int i=0;i<e[now].size();i++)if(!--deg[e[now][i]])q.push(e[now][i]);
}
}
去重
void unique(int n,vector<pair<int,long long>>e[]){
for(int i=1;i<=n;i++)sort(e[i].begin(),e[i].end()),e[i].erase(unique(e[i].begin(),e[i].end()),e[i].end());
}
欧拉回路(Hierholzer)
void dfs1(int pos,edge e[],int head[],bool vis[],int ans[],int &cnt){
for(int i=head[pos];i;i=head[pos]){
head[pos]=e[i].nxt;
if(!vis[i])vis[i]=vis[i^1]=1,dfs1(e[i].v,e,head,vis,ans,cnt),ans[++cnt]=(i&1?-i/2:i/2);
}
}
bool hierholzer1(int n,int m,edge e[],int head[],int ans[]){
int deg[n+5],cnt=0;
bool vis[m*2+5];
memset(deg,0,sizeof(deg)),memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)for(int j=head[i];j;j=e[j].nxt)deg[e[j].v]++,deg[i]++;
for(int i=1;i<=n;i++)if(deg[i]/2&1)return 0;
for(int i=1;i<=n;i++){
if(deg[i]){
dfs1(i,e,head,vis,ans,cnt);
break;
}
}
if(cnt!=m)return 0;
return 1;
}//undirected
void dfs2(int pos,edge e[],int head[],int ans[],int &cnt){
for(int i=head[pos];i;i=head[pos])head[pos]=e[i].nxt,dfs2(e[i].v,e,head,ans,cnt),ans[++cnt]=i-1;
}
bool hierholzer2(int n,int m,edge e[],int head[],int ans[]){
int deg[n+5],out[n+5],cnt=0;
memset(deg,0,sizeof(deg)),memset(out,0,sizeof(out));
for(int i=1;i<=n;i++)for(int j=head[i];j;j=e[j].nxt)deg[e[j].v]++,out[i]++;
for(int i=1;i<=n;i++)if(out[i]!=deg[i])return 0;
for(int i=1;i<=n;i++){
if(out[i]){
dfs2(i,e,head,ans,cnt);
break;
}
}
if(cnt!=m)return 0;
return 1;
}//directed
无向图三元环计数
vector<int>t[n+5];
int deg[n+5],vis[n+5],ans=0;
int cyc(int n,vector<int>e[],int ans=0){
for(int i=1;i<=n;i++)for(int j=0;j<e[i].size();i++)deg[e[i][j]]++;
for(int i=1;i<=n;i++)for(int j=0;j<e[i].size();j++)if(deg[i]>deg[e[i][j]]||(deg[i]==deg[e[i][j]]&&i<e[i][j]))t[i].push_back(e[i][j]);
for(int i=1;i<=n;i++){
for(int j=0;j<t[i].size();j++)vis[t[i][j]]=i;
for(int j=0;j<t[i].size();j++)for(int k=0;k<t[t[i][j]].size();k++)if(vis[t[t[i][j]][k]]==i)ans++;
}
return ans;
}
二分图最大匹配
bool vis[m+5];
bool dfs(int pos,vector<int>e[],int a[]){
for(int i=0;i<e[pos].size();i++){
if(!vis[e[pos][i]]){
vis[e[pos][i]]=1;
if(!a[e[pos][i]]||dfs(a[e[pos][i]],e,a))return a[e[pos][i]]=pos,1;
}
}
return 0;
}
int match(int n,vector<int>e[],int a[],int ans=0){
for(int i=1;i<=n;i++)memset(vis,0,sizeof(vis)),ans+=dfs(i,e,a);
return ans;
}