我的塔尖模板有什么问题???
  • 板块学术版
  • 楼主夜阑
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/10/2 14:25
  • 上次更新2023/11/4 05:09:39
查看原帖
我的塔尖模板有什么问题???
243263
夜阑楼主2021/10/2 14:25
#include<iostream>
using namespace std;
struct node{int w,next,to;};//w:权值,next:同一起点的下一条边的序号,to终点
node bian[10010];//边
int head[10001];//起点的索引表
int n,m,num,cnt,bcnt;
//n个点m条边num是时间序号,cnt是强连通分量(出栈次数),bcnt记录边的条数
int vist[10010];//标记有没有访问过
int ins[10010];//标记顶点在不在栈中
int sp=1;//栈顶指针
int zhan[10010];//栈
int dfn[10010];//每个顶点是第几个被访问的
int low[10010];//标记是不是一伙人,如果出边被遍历完且dfn[]==low[]就出栈
//low[x]=min(low[x],dfn[y]);x遍历到y
void push(int x){//入栈
    zhan[sp++]=x;
}
int pop(){//出栈
    if(sp==1)//栈空
        return 987654321;
    else sp--;
}
void add(int x,int y,int w){//起点终点权值
    bcnt++;//bcnt:边的总条数
    bian[bcnt].w=w;//终点赋值 
    bian[bcnt].to=y;//权值赋值 
    bian[bcnt].next=head[x];//当前同一起点下一条边的序号设置 
    head[x]=bcnt;//头插法:x的第一条出边修改为当前边序号设置 
}
void tj(int x){//开始遍历tarjan,求强连通分量个数,缩点
    int y,i,t;
    num++;//访问的顶点次序(时间轴)+1;
    dfn[x]=low[x]=num;//默认的low=dfn,后面low有可能被刷新变小
    push(x);//tj入栈
    ins[x]=1;//在栈中做标记
    vist[x]=1;//标记x已经被标记过了
    for(int i=head[x];i;i=bian[i].next){//扫描x的所有出边
        y=bian[i].to;
        if(vist[y]==0){//第1种情况:y没有被访问
            tj(y);//继续递归以y为起点
            low[x]=min(low[x],dfn[y]);//递归回填改变low,同一个强连通分量的low基本相同(不一定)
        }
        else {//y已经被访问过,判断y是否在栈中,如果不在栈中y就已经是其他的连通分量的一个点,跳过
            if(ins[y]==1){//y已经被访问过了并且y在栈中,说明x->y是返祖边
                //不要递归了,直接修改low
                low[x]=min(low[x],dfn[y]);
            }
        }
    }//for循环结束后,x的所有出边穷举完毕,判断low[x]==dfn[x],如果相等就一直出栈直到x点出栈,这一次出栈的所有点是同一个强连通分量
    if(low[x]==dfn[x]){//如果x找到了所有能作为同一个强连通分量的顶点后,同一个强连通分量的所有点开始出栈直到x出栈
        cnt++;//强连通分量的个数+1;
        cout<<"第"<<cnt<<"个强连通分量的元素为:";
        do{//方便判断用do-while
            t=pop();//出栈
            if(t==987654321)break;//栈空则停止
            cout<<" "<<t;//输出元素
            ins[t]=0;//出栈标记
        }
        while(t!=x);//x出栈后就停止
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        add(x,y,1);
    }
    for(int i=1;i<=n;i++){//防止有的强连通分量是单独的,不与别的强连通分量有边相连导致找不到
        if(vist[i]==0)tj(i);
    }
    cout<<"总的强联通分量的个数为:"<<cnt<<endl;
    for(int i=1;i<=n;i++){
        cout<<"第"<<i<<"个点的low值为:"<<low[i]<<endl;
    }
    return 0;
}
2021/10/2 14:25
加载中...