Cod sursa(job #3186285)

Utilizator razviOKPopan Razvan Calin razviOK Data 22 decembrie 2023 16:31:10
Problema Componente tare conexe Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 11.05 kb
#include <stdio.h>
#include <stdlib.h>



enum Colour{White,Gray,Black};
typedef struct Node{
    int key;
    Colour colour;
    int discovery_time,finish_time;
    Node *parent;

    int index;
    int comp;
    int low_link;
    bool onStack;

    int adjListSize;
    Node **adjList;
};
typedef struct Graph{
    int graph_size;
    Node **vertices;
};

int time=0,numCC=0,cnt=0,index=0,numSCC=0,stack_end=0;
int Minimum(int a,int b){
    return (a<b) ? a:b;
}
void DestroyGraph(Graph *graph){
    for(int i=0;i<graph->graph_size;i++){

        free(graph->vertices[i]->parent);
        graph->vertices[i]->parent=NULL;

        free(graph->vertices[i]->adjList);
        graph->vertices[i]->adjList=NULL;

        graph->vertices[i];
        free(graph->vertices[i]);
        graph->vertices[i]=NULL;
    }

    free(graph->vertices);
    graph->vertices=NULL;
}
void DFS_VISIT(Node *current_node,int space,Node **topSortNodes){

    for(int i=0;i<space;i++)
        printf("  ");
    printf("%d\n",current_node->key);

    time+=1;
    current_node->colour=Gray;
    current_node->discovery_time=time;
    for(int i=0;i<current_node->adjListSize;i++)
        if(current_node->adjList[i]->colour==White) {
            DFS_VISIT(current_node->adjList[i],space+1,topSortNodes);
        }

    current_node->colour=Black;
    time+=1;
    current_node->finish_time=time;

    if(NULL!=topSortNodes)
        topSortNodes[--cnt]=current_node;
}
void DFS(Graph *graph,Node **topSortNodes){

    for(int i=0;i<graph->graph_size;i++){
        graph->vertices[i]->colour=White;
        graph->vertices[i]->discovery_time=0;
        graph->vertices[i]->finish_time=0;
        graph->vertices[i]->parent=NULL;
    }

    time=0;
    numCC=0;
    cnt=graph->graph_size;
    for(int i=0;i<graph->graph_size;i++)
        if(graph->vertices[i]->colour==White) {
            DFS_VISIT(graph->vertices[i],0,topSortNodes);
            numCC++;
        }

}
void TopologicalSort(Graph *graph){

    Node **topSortNodes=(Node **) malloc(sizeof(Node *)*graph->graph_size);

    DFS(graph,topSortNodes);
    printf("Array of sorted nodes using topological sort:");
    for(int i=0;i<graph->graph_size;i++)
        printf("%d ",topSortNodes[i]->key);
    printf("\n");

    free(topSortNodes);
}
void StrongConnect(Node *current_node,Node **Stack,Node ***SCC,int *SCCsize){
  current_node->index=index;
  current_node->low_link=index;
  index+=1;

  Stack[stack_end++]=current_node;
  current_node->onStack= true;

  for(int i=0;i<current_node->adjListSize;i++) {
      if (current_node->adjList[i]->index == -1) {
          StrongConnect(current_node->adjList[i], Stack,SCC,SCCsize);
          current_node->low_link = Minimum(current_node->low_link, current_node->adjList[i]->low_link);
      } else if (current_node->adjList[i]->onStack)
          current_node->low_link = Minimum(current_node->low_link, current_node->adjList[i]->index);
  }

  if(current_node->low_link==current_node->index){
      int cnt=0;
      numSCC+=1;
      while(stack_end>0 && current_node!=Stack[stack_end-1]){
              SCC[numSCC-1][cnt++]=Stack[stack_end-1];
              Stack[stack_end - 1]->onStack = false;
              Stack[stack_end - 1]->comp = numSCC;
              stack_end--;
      }

      if(current_node==Stack[stack_end-1]){
          SCC[numSCC-1][cnt++]=Stack[stack_end-1];
          Stack[stack_end - 1]->onStack = false;
          Stack[stack_end - 1]->comp = numSCC;
          stack_end--;
      }
      SCC[numSCC-1]=(Node **) realloc(SCC[numSCC-1],cnt* sizeof(Node *));
      SCCsize[numSCC-1]=cnt;
  }
}
void Tarjan(Graph *graph){
    index=0;
    Node **Stack=(Node **) malloc(sizeof(Node *)*graph->graph_size);
    Node ***SCC=(Node ***) malloc(sizeof(Node **)*graph->graph_size);
    int *SCCsize=(int *) malloc(sizeof(int)*graph->graph_size);

    for(int i=0;i<graph->graph_size;i++)
        SCC[i]=(Node **) malloc(sizeof(Node *)*graph->graph_size);

    numSCC=0;
    stack_end=0;

    for(int i=0;i<graph->graph_size;i++){
        graph->vertices[i]->index=-1;
        graph->vertices[i]->onStack=false;
        graph->vertices[i]->comp=0;
        graph->vertices[i]->low_link=-1;
    }

    for(int i=0;i<graph->graph_size;i++)
        if(graph->vertices[i]->index==-1){
            StrongConnect(graph->vertices[i],Stack,SCC,SCCsize);
        }

//    printf("Number of Strongly connected components:%d",numSCC);
    printf("%d\n",numSCC);
    SCC=(Node ***) realloc(SCC,numSCC* sizeof(Node**));
    for(int i=0;i<numSCC;i++){
        for(int j=0;j<SCCsize[i];j++)
            printf("%d ",SCC[i][j]->key);
        printf("\n");
    }

    for(int i=0;i<numSCC;i++)
        free(SCC[i]);

    free(SCC);
    free(SCCsize);
    free(Stack);
}
void Undirected(){
    Graph graph;
    int n,m,x,y;
    scanf("%d",&n);
    scanf("%d",&m);

    graph.graph_size=n;
    graph.vertices=(Node **) malloc(sizeof(Node *)*n);
    for(int i=0;i<graph.graph_size;i++) {
        graph.vertices[i] = (Node *) malloc(sizeof(Node));
        graph.vertices[i]->adjListSize=0;
        graph.vertices[i]->key=i+1;
        graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
    }

    for(int i=0;i<m;i++){
        scanf("%d",&x);
        scanf("%d",&y);

        graph.vertices[x-1]->adjList=(Node **) realloc(graph.vertices[x-1]->adjList, sizeof(Node *)*(graph.vertices[x-1]->adjListSize+1));
        graph.vertices[y-1]->adjList=(Node **) realloc(graph.vertices[y-1]->adjList, sizeof(Node *)*(graph.vertices[y-1]->adjListSize+1));

        graph.vertices[x-1]->adjList[graph.vertices[x-1]->adjListSize++]=graph.vertices[y-1];
        graph.vertices[y-1]->adjList[graph.vertices[y-1]->adjListSize++]=graph.vertices[x-1];
    }

    DFS(&graph,NULL);
    printf("%d",numCC);
    DestroyGraph(&graph);
}
void DemoDFS(){

    printf("---DEMO DFS---\n");
    Graph graph;
    int n=5,m=5,x,y;


    graph.graph_size=n;
    graph.vertices=(Node **) malloc(sizeof(Node *)*n);
    for(int i=0;i<graph.graph_size;i++) {
        graph.vertices[i] = (Node *) malloc(sizeof(Node));
        graph.vertices[i]->adjListSize=0;
        graph.vertices[i]->key=i+1;
        graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
    }

    int arr1[5]={1,2,2,4,5};
    int arr2[5]={2,3,4,5,3};

    for(int i=0;i<m;i++){
        graph.vertices[arr1[i]-1]->adjList=(Node **) realloc(graph.vertices[arr1[i]-1]->adjList, sizeof(Node *)*(graph.vertices[arr1[i]-1]->adjListSize+1));
        graph.vertices[arr1[i]-1]->adjList[graph.vertices[arr1[i]-1]->adjListSize++]=graph.vertices[arr2[i]-1];
    }

    printf("Graph\n");
    for(int i=0;i<graph.graph_size;i++){
        printf("%d adjacency list:",graph.vertices[i]->key);
        for(int j=0;j<graph.vertices[i]->adjListSize;j++)
            printf("%d ",graph.vertices[i]->adjList[j]->key);

        printf("\n");
    }

    printf("DFS Tree:\n");
    DFS(&graph,NULL);
    DestroyGraph(&graph);
}
void DemoTopSort(){

    printf("---DEMO TOPOLOGICAL SORT---\n");
    Graph graph;
    int n=9,m=8,x,y;


    graph.graph_size=n;
    graph.vertices=(Node **) malloc(sizeof(Node *)*n);
    for(int i=0;i<graph.graph_size;i++) {
        graph.vertices[i] = (Node *) malloc(sizeof(Node));
        graph.vertices[i]->adjListSize=0;
        graph.vertices[i]->key=i+1;
        graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
    }

    int arr1[8]={1,1,3,3,5,4,4,4};
    int arr2[8]={2,3,4,5,9,6,7,8};

    for(int i=0;i<m;i++){
        graph.vertices[arr1[i]-1]->adjList=(Node **) realloc(graph.vertices[arr1[i]-1]->adjList, sizeof(Node *)*(graph.vertices[arr1[i]-1]->adjListSize+1));
        graph.vertices[arr1[i]-1]->adjList[graph.vertices[arr1[i]-1]->adjListSize++]=graph.vertices[arr2[i]-1];
    }

    printf("Graph\n");
    for(int i=0;i<graph.graph_size;i++){
        printf("%d adjacency list:",graph.vertices[i]->key);
        for(int j=0;j<graph.vertices[i]->adjListSize;j++)
            printf("%d ",graph.vertices[i]->adjList[j]->key);

        printf("\n");
    }

    printf("DFS Tree:\n");
    TopologicalSort(&graph);
    DestroyGraph(&graph);

}
void Directed(){
    Graph graph;
    int n,m,x,y;
    scanf("%d",&n);
    scanf("%d",&m);

    graph.graph_size=n;
    graph.vertices=(Node **) malloc(sizeof(Node *)*n);
    for(int i=0;i<graph.graph_size;i++) {
        graph.vertices[i] = (Node *) malloc(sizeof(Node));
        graph.vertices[i]->adjListSize=0;
        graph.vertices[i]->key=i+1;
        graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
    }

    for(int i=0;i<m;i++){
        scanf("%d",&x);
        scanf("%d",&y);
        graph.vertices[x-1]->adjList=(Node **) realloc(graph.vertices[x-1]->adjList, sizeof(Node *)*(graph.vertices[x-1]->adjListSize+1));
        graph.vertices[x-1]->adjList[graph.vertices[x-1]->adjListSize++]=graph.vertices[y-1];
    }

    TopologicalSort(&graph);
    DestroyGraph(&graph);
}
void DemoTarjan(){
    printf("---DEMO TARJAN SCC---\n");
    Graph graph;
    int n=8,m=12,x,y;

    graph.graph_size=n;
    graph.vertices=(Node **) malloc(sizeof(Node *)*n);
    for(int i=0;i<graph.graph_size;i++) {
        graph.vertices[i] = (Node *) malloc(sizeof(Node));
        graph.vertices[i]->adjListSize=0;
        graph.vertices[i]->key=i+1;
        graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
        graph.vertices[i]->low_link=0;
        graph.vertices[i]->index=0;
        graph.vertices[i]->onStack=false;
    }

    int arr1[12]={1,2,6,7,3,3,2,4,5,6,5,8};
    int arr2[12]={2,6,7,6,1,4,3,5,4,5,8,7};

    for(int i=0;i<m;i++){
        graph.vertices[arr1[i]-1]->adjList=(Node **) realloc(graph.vertices[arr1[i]-1]->adjList, sizeof(Node *)*(graph.vertices[arr1[i]-1]->adjListSize+1));
        graph.vertices[arr1[i]-1]->adjList[graph.vertices[arr1[i]-1]->adjListSize++]=graph.vertices[arr2[i]-1];
    }

    printf("Graph\n");
    for(int i=0;i<graph.graph_size;i++){
        printf("%d adjacency list:",graph.vertices[i]->key);
        for(int j=0;j<graph.vertices[i]->adjListSize;j++)
            printf("%d ",graph.vertices[i]->adjList[j]->key);

        printf("\n");
    }

    Tarjan(&graph);
    DestroyGraph(&graph);
}
void SolveSCC(){

        Graph graph;
        int n,m,x,y;
        scanf("%d",&n);
        scanf("%d",&m);

        graph.graph_size=n;
        graph.vertices=(Node **) malloc(sizeof(Node *)*n);
        for(int i=0;i<graph.graph_size;i++) {
            graph.vertices[i] = (Node *) malloc(sizeof(Node));
            graph.vertices[i]->adjListSize=0;
            graph.vertices[i]->key=i+1;
            graph.vertices[i]->adjList=(Node **) malloc(sizeof(Node *));
        }

        for(int i=0;i<m;i++){
            scanf("%d",&x);
            scanf("%d",&y);
            graph.vertices[x-1]->adjList=(Node **) realloc(graph.vertices[x-1]->adjList, sizeof(Node *)*(graph.vertices[x-1]->adjListSize+1));
            graph.vertices[x-1]->adjList[graph.vertices[x-1]->adjListSize++]=graph.vertices[y-1];
        }

        Tarjan(&graph);

    DestroyGraph(&graph);
}
int main() {

//    freopen("dfs.in","r",stdin);
//    freopen("dfs.out","w",stdout);
    freopen("ctc.in","r",stdin);
    freopen("ctc.out","w",stdout);
//    Undirected();
//    DemoDFS();
//    DemoTopSort();
//    DemoTarjan();
//   Directed();
    SolveSCC();

    return 0;
}