[PTA] Strongly Connected Components

本文详细介绍了如何使用Tarjan算法来识别图中的强连通分量,并提供了一个C语言实现的示例。通过遍历图中的每个顶点并应用深度优先搜索(DFS),该算法能有效地找出所有强连通分量,为理解复杂图结构提供了有力工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 算法参考了网上资料(Tarjan算法),嫌麻烦并没有使用给出的函数指针。

#include <stdio.h>
#include <stdlib.h>

#define MaxVertices 10  /* maximum number of vertices */
typedef int Vertex;     /* vertices are numbered from 0 to MaxVertices-1 */
typedef struct VNode *PtrToVNode;
struct VNode {
    Vertex Vert;
    PtrToVNode Next;
};
typedef struct GNode *Graph;
struct GNode {
    int NumOfVertices;
    int NumOfEdges;
    PtrToVNode *Array;
};

Graph ReadG(); /* details omitted */

void PrintV( Vertex V )
{
   printf("%d ", V);
}

void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) );

int main()
{
//    freopen("test.txt","r",stdin);
    Graph G = ReadG();
    StronglyConnectedComponents( G, PrintV );
    return 0;
}

PtrToVNode insert(PtrToVNode p,int x)
{
    p->Next=(PtrToVNode)malloc(sizeof(struct VNode));
    p=p->Next;
    p->Vert=x;
    p->Next=NULL;
    return p;
}

Graph ReadG()
{
    //乱七八糟的指针操作真是报警了好嘛
    //就不能愉快地使用邻接矩阵吗
    //反正你们也不会看这里我就吐槽下 
    int i,j,m,n,x,y;
    scanf("%d%d",&m,&n); 
    Graph p=(Graph)malloc(sizeof(struct GNode));
    PtrToVNode *rear=(PtrToVNode*)malloc(m*sizeof(struct VNode));
    p->Array=(PtrToVNode*)malloc(m*sizeof(struct VNode));
    p->NumOfVertices=m;
    p->NumOfEdges=n;
    for(i=0;i<m;i++){
        rear[i]=p->Array[i]=(PtrToVNode)malloc(sizeof(struct VNode));
        p->Array[i]->Next=NULL;
    }
    for(i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        rear[x]=insert(rear[x],y);
    }
    for(i=0;i<m;i++){
        PtrToVNode tmp=p->Array[i];
        p->Array[i]=p->Array[i]->Next;
        tmp->Next=NULL;
        free(tmp);
    } 
    return p;
}

int visited[MaxVertices];//判断是否访问过该节点(是否在堆栈里) 
int dfn[MaxVertices];//dfn[i]存储i是第几个访问的点(即访问次序) 
int low[MaxVertices];//low[i]存储和i连接的数字中最早访问次序号 
int path[MaxVertices];//堆栈 
int flag[MaxVertices];//判断顶点是否已经输出 

int index=0;//记录访问次数 
int cnt=0;//记录堆栈当前元素个数 

int min(int x,int y)
{
    return x<y?x:y;
}

int pop()
{
    return path[--cnt];
}

void push(int x)
{
    path[cnt++]=x;
}

void dfs(Graph G,int v);

void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) )
{
    int i;
    for(i=0;i<G->NumOfVertices;i++){
        visited[i]=0;
        flag[i]=0;
        dfn[i]=low[i]=-1;
    }
    for(i=0;i<G->NumOfVertices;i++){
        if(!flag[i])dfs(G,i);
    }
}

void dfs(Graph G,int v)
{
    int i;
    low[v]=dfn[v]=index++;
    visited[v]=1;
    PtrToVNode p=G->Array[v];
    push(v);
    while(p){
        i=p->Vert;
        if(dfn[i]==-1){
            dfs(G,i);
            low[v]=min(low[v],low[i]);
        }
        else if(visited[i]){
            low[v]=min(low[v],dfn[i]);
        }
        p=p->Next;
    }
    if(dfn[v]==low[v]){
        int t;
        do{
            t=pop();
            visited[t]=0;
            flag[t]=1;
            printf("%d ",t);
        }while(t!=v);
        printf("\n");
    }
    return;
}
/* Your function will be put here */


 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值