图论

链式前向星

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;
}
posted @ 2024-03-01 09:38  lgh_2009  阅读(9)  评论(0)    收藏  举报