关于基础知识的预备桥和割点双联通分量强连通分量支配树(并不会支配树)

关于有向图的Tarjan,是在熟悉不过的了,它的主要功能就是求强联通分量,缩个点,但是要注意一下构建新图的时候有可能出现重边(即使原图没有重边),他还时常和拓扑排序放在一起。eg:

#include<cstdio>
#include<cstring>
#include<algorithm>
char xB[(1<<15)+10],*xS=xB,*xT=xB;
#define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
inline void read(int &x){
    register char ch=gtc;
    for(x=0;ch<'0'||ch>'9';ch=gtc);
    for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);
}
const int N=100010;
const int M=1000010;
struct V{int to,next;}c[M<<1];
int head[N],e[N],t;
inline void add(int x,int y,int *id){
    c[++t].to=y,c[t].next=id[x],id[x]=t;
}
int dfn[N],low[N],Ti,belong[N],stack[N],top,num,size[N];
bool in[N];
int n,m;
int f[N],sum[N],degree[N];
int q[N],front=1,tail;
int ans,fin,P;
int visit[N];
inline void Tarjan(int x){
    dfn[x]=low[x]=++Ti,in[x]=true,stack[++top]=x;
    for(int i=head[x];i;i=c[i].next)
        if(dfn[c[i].to]==0)
            Tarjan(c[i].to),low[x]=std::min(low[x],low[c[i].to]);
        else if(in[c[i].to])
            low[x]=std::min(low[x],dfn[c[i].to]);
    if(low[x]==dfn[x]){
        int j;++num;
        do{
            j=stack[top--],in[j]=false,belong[j]=num,++size[num];
        }while(j!=x);
    }
}
int main(){
    read(n),read(m),read(P);
    for(int i=1,x,y;i<=m;++i)
        read(x),read(y),add(x,y,head);
    for(int i=1;i<=n;++i)
        if(dfn[i]==0)Tarjan(i);
    for(int x=1;x<=n;++x)
        for(int i=head[x];i;i=c[i].next)
            if(belong[x]!=belong[c[i].to])
                add(belong[x],belong[c[i].to],e),++degree[belong[c[i].to]];
    for(int i=1;i<=num;++i){
        if(degree[i]==0)q[++tail]=i;
        sum[i]=1;
    }
    while(front<=tail){
        int x=q[front++];
        f[x]+=size[x];
        if(f[x]>ans)ans=f[x],fin=sum[x];
        else if(f[x]==ans)fin=(fin+sum[x])%P;
        for(int i=e[x];i;i=c[i].next){
            --degree[c[i].to];
            if(visit[c[i].to]!=x){
                if(f[x]>f[c[i].to])f[c[i].to]=f[x],sum[c[i].to]=sum[x];
                else if(f[x]==f[c[i].to])sum[c[i].to]=(sum[c[i].to]+sum[x])%P;
                visit[c[i].to]=x;
            }
            if(degree[c[i].to]==0)q[++tail]=c[i].to;
        }
    }
    printf("%d\n%d",ans,fin);
    return 0;
}
【BZOJ 1093】[ZJOI2007]最大半连通子图

相关文章:

  • 2022-12-23
  • 2021-08-26
  • 2022-12-23
  • 2022-12-23
  • 2021-12-02
  • 2021-11-24
  • 2021-12-27
  • 2021-12-19
猜你喜欢
  • 2021-05-26
  • 2021-12-09
  • 2022-12-23
  • 2022-01-20
  • 2021-11-28
  • 2021-08-31
相关资源
相似解决方案