##连通性##


//强联通
struct edge{
    int to,next,num;  //增设num为判重边
}e[M];
int scc,hea,tim;
int low[N],dfs[N],tr[N],sccno[N];
int head[N],o;//记得初始化
void add(int x,int y,int m)
{
    e[o].to=y;
    e[o].next=head[x];
    e[o].num=m;
    head[x]=o++;
}
scanf("%d%d",&x,&y);{add(x,y,i); add(y,x,i);}
void tarjandfs(int now,int from)
{   int v;
    tr[++hea]=now; in[now]=1;
    dfs[now]=++tim; low[now]=dfs[now];
    for (int k=head[now];k!=-1;k=e[k].next)
        {   v=e[k].to;
            if (e[k].num==from) continue; //imp!
            if (dfs[v]==0)//生成树的边
                {tarjandfs(v,e[k].num);  low[now]=min(low[now],low[v]);
                }
            else if (in[v])//回边
            low[now]=min(low[now],dfs[v]);
        }
    /*具体剥离出每个强连通分量,一般用于一般有向图*/
    if(low[now]==dfs[now])
          { int i;
            scc++;
            do{i=tr[hea--];  sccno[i]=scc; in[i]=0;}while(i!=now);
          }

}
//因为有向图除了树枝边、回边还有交叉边,所以in数组不可少。而无向图没有交叉边(除了树枝边就是回边),故可以直接else而省去in数组。
主函数:
tcc=tim=hea=0;memset(dfs,0,sizeof(dfs));memset(low,0,sizeof(low));memset(in,0,sizeof(in));//初始化
tarjandfs(1,-1);//前提:题目保证是个连通图(弱连通)
//否则要for (i=1;i<=n;i++) if (!dfs[i]) tarjandfs(i,-1);
1.求割边
if (dfs[now]<low[v]&&e[k].num==1) an[ans++]=e[k].id;
2.去掉关节点u,将连通图分成几个连通分量?
(1).u是关节点,几个儿子几个分量(2)不是根节点,d个子女w,满足low[w]>=dfn[u],为d+1个分量
具体实现:for (i=1;i<=max;i++) ans[i]=1; ans[1]=0;
//ans[i]=1代表i上头的那一部分(有根的那部分)
//&&在low[now]=min(low[now],low[v]);这句话后面加if (dfs[u]<=low[w]) ans[u]++;



//双联通
//代码1
int dfs[N],low[N],bccno[N];//3个数组均memset为0
int n,m;
int tim,bcc;
struct edge{
    int u,v;
    edge(int x=0,int y=0):u(x),v(y){}
}e[M];
vector<int > BCC[N],g[N];
bool iscut[N];//初始化为0
stack<edge> S;

int tarjandfs(int u,int from=-1)
{   int lowu=dfs[u]=++tim;
    int child=0;
    for (int i=0;i<g[u].size();i++)
        {   int v=g[u][i];
            edge e=edge(u,v);
            if (!dfs[v])
                {
                    S.push(e);
                    child++;
                    int lowv=tarjandfs(v,u);
                    lowu=min(lowu,lowv);
                    if (lowv>=dfs[u])
                        {   iscut[u]=1;
                            bcc++; BCC[bcc].clear();
                            while (1)
                                {
                                    edge x=S.top(); S.pop();
                                    if (bccno[x.u]!=bcc) {BCC[bcc].pb(x.u);bccno[x.u]=bcc;}
                                    if (bccno[x.v]!=bcc) {BCC[bcc].pb(x.v);bccno[x.v]=bcc;}
                                    if (x.u==u&&x.v==v) break;
                                }

                        }
                }
            else if (dfs[v]<dfs[u]&&v!=from){
                S.push(e);
                lowu=min(lowu,dfs[v]);
            }
        }
    if (from<0&&child==1) iscut[u]=0;
    return lowu;
}
//bcc=tim=0;
//memset(iscut,0,sizeof(iscut));
//memset(dfs,0,sizeof(dfs));
//memset(low,0,sizeof(low));
//memset(bccno,0,sizeof(bccno));
//for (int i=1;i<=n;i++)if (!dfs[i]) tarjandfs(i,-1);
//S保证第一组数据前是empty的

//双联通
//代码2
int dfs[N],low[N],bccno[N];//3个数组均memset为0
int tr[N];
int n,m;
int tim,bcc,hea;
vector<int > BCC[N],g[N];
bool iscut[N],vv[N];//2个初始化为0
void tarjandfs(int u,int from=-1)
{   low[u]=dfs[u]=++tim;
    tr[++hea]=u; vv[u]=1;
    int child=0;
    for (int i=0;i<g[u].size();i++)
        {   int v=g[u][i];
            if (v==from) continue;
            if (!dfs[v])
                {   tarjandfs(v,u);child++;
                    low[u]=min(low[u],low[v]);
                    if (dfs[u]<=low[v])
                        {   iscut[u]=1;
                            int x;
                            bcc++;BCC[bcc].clear();
                            do{x=tr[hea--];  bccno[x]=bcc; BCC[bcc].pb(x); vv[x]=0; }while(x!=v);
                            BCC[bcc].pb(u);
                       }
                }
            else if (vv[v])
                low[u]=min(low[u],dfs[v]);
        }
    if (from<0&&child==1) iscut[u]=0;
}
//bcc=tim=hea=0;
//memset(dfs,0,sizeof(dfs));
//memset(low,0,sizeof(low));
//memset(bccno,0,sizeof(bccno));
//memset(vv,0,sizeof(vv));
//memset(iscut,0,sizeof(iscut));
//for (int i=1;i<=n;i++)if (!dfs[i]) tarjandfs(i,-1);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值