Revision 77a38bc262181e4fc7952f213617e01965271543 authored by KoGi89 on 01 February 2021, 12:06:31 UTC, committed by GitHub on 01 February 2021, 12:06:31 UTC
1 parent ef7d7cf
Raw File
Tsin-2E.cpp
//usage: ./Tsin <input_graph> <output_file>

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

int n, m;
int* edges;
int* G; int* firstOut;

void create_adj();
void find_cut_edges();
int* cut_edges;
int n_cut_edges;

int* dfs; int* nd; int* lowpt; int* low; int* lowpt2; int* low2; int* tolow; int* parent;
int Nr=1;

void Find_cut_pairs(int);
int* tree_edge_is_cutEdge; int* back_edge_is_cutEdge;
void insert_edge(int,int,char);

int* STACK; int* firstIndx; int* prevIndx;
int SP=0;
void push(int,int,int,int,int);
void pop(int);


int main(int n_args, char** args)
{
   FILE* fp = fopen(args[1],"r");
   fscanf(fp,"%d %d",&n,&m);
   edges = (int*)malloc(sizeof(int)*2*m);
   for(int i=0;i<m;i++)
   {
      int x,y;
      fscanf(fp,"%d %d",&x,&y);
      edges[2*i]=x-1; edges[2*i+1]=y-1;
   }
   fclose(fp);

   create_adj();

   struct timeval begin, end;
   gettimeofday(&begin, 0);  

   find_cut_edges();

   //count cut-pairs
   int n_cut_pairs=0;
   for(int i=0;i<n;i++)
   {
      int c=tree_edge_is_cutEdge[i];
      n_cut_pairs+=(c*(c+1))/2;
      c=back_edge_is_cutEdge[i];
      n_cut_pairs+=(c*(c+1))/2;
   }

   gettimeofday(&end, 0);
	long seconds = end.tv_sec - begin.tv_sec;
	long microseconds = end.tv_usec - begin.tv_usec;
	double elapsed = seconds + microseconds*1e-6;
	printf("Total time= %g\n", elapsed);

   fp = fopen(args[2],"w");
   fprintf(fp,"%d\n",n_cut_edges);
   for(int i=0;i<n_cut_edges;i++)
   {
      fprintf(fp,"%d %d\n",cut_edges[2*i]+1,cut_edges[2*i+1]+1);
   }
   fprintf(fp,"%d\n",n_cut_pairs);
   fprintf(fp, "%lf\n", elapsed);
   fclose(fp);
   
   return 0;
}

void push(int v, int x, int y, int p, int q)
{
   prevIndx[SP]=firstIndx[v];
   firstIndx[v]=SP;
   int sp=SP*4;
   STACK[sp]=x;
   STACK[sp+1]=y;
   STACK[sp+2]=p;
   STACK[sp+3]=q;
   SP++;
}

void pop(int v)
{
   firstIndx[v]=prevIndx[firstIndx[v]];
}

void find_cut_edges()
{
   cut_edges = (int*)malloc(sizeof(int)*(4*n-4));
   n_cut_edges = 0;

   tree_edge_is_cutEdge = (int*)malloc(sizeof(int)*n);
   back_edge_is_cutEdge = (int*)malloc(sizeof(int)*n);
   for(int i=0;i<n;i++)
   {
      tree_edge_is_cutEdge[i]=0;
      back_edge_is_cutEdge[i]=0;
   }
 
   dfs = (int*)malloc(sizeof(int)*n); 
   for(int i=0;i<n;i++){dfs[i]=-1;}
   parent = (int*)malloc(sizeof(int)*n); 
   nd = (int*)malloc(sizeof(int)*n);   
   lowpt = (int*)malloc(sizeof(int)*n);   
   low = (int*)malloc(sizeof(int)*n);   
   lowpt2 = (int*)malloc(sizeof(int)*n);   
   low2 = (int*)malloc(sizeof(int)*n);   
   tolow = (int*)malloc(sizeof(int)*n);  

   STACK = (int*)malloc(sizeof(int)*m*4);
   firstIndx = (int*)malloc(sizeof(int)*n);
   for(int i=0;i<n;i++){firstIndx[i]=-1;}
   prevIndx = (int*)malloc(sizeof(int)*m);

   parent[0]=-1; 
   Find_cut_pairs(0);  
}

void Find_cut_pairs(int v)
{
   dfs[v]=Nr++;
   nd[v]=1;
   lowpt[v]=dfs[v]; low[v]=v;
   lowpt2[v]=dfs[v]; low2[v]=v;

   int* temp_vertex = (int*)malloc(sizeof(int)*n);
   int* temp_out = (int*)malloc(sizeof(int)*n);
   char* firstTime = (char*)malloc(sizeof(char)*n);
   for(int i=0;i<n;i++){firstTime[i]=0;}
   int stack_pointer=0;
   
   temp_vertex[0]=v; temp_out[0]=firstOut[v];

while(stack_pointer!=-1)
{
   v=temp_vertex[stack_pointer];
   char descend=0;

   //1
   for(int i=temp_out[stack_pointer];i<firstOut[v+1];i++)
   {
      int w=G[i];
      //1.1
      if(dfs[w]==-1)
      {
         parent[w]=v;
         dfs[w]=Nr++;
         nd[w]=1;
         lowpt[w]=dfs[w]; low[w]=w;
         lowpt2[w]=dfs[w]; low2[w]=w;
         temp_vertex[stack_pointer+1]=w; temp_out[stack_pointer+1]=firstOut[w];
         temp_out[stack_pointer]=i; firstTime[stack_pointer]=1;
         descend=1; break;
      }
      if(firstTime[stack_pointer])
      {
         firstTime[stack_pointer]=0;
         //1.1.1
         if(firstIndx[w]!=-1)
         {
            int sp=firstIndx[w]*4;
            int x=STACK[sp];
            int y=STACK[sp+1];
            int p=STACK[sp+2];
            int q=STACK[sp+3];
            if(w==q)
            {
               pop(w);
               //printf("(%d,%d) (%d,%d)\n",v+1,w+1,x+1,y+1);
               insert_edge(x,y,1);
               insert_edge(v,w,0);
               if(v!=p)
               {
                  push(w,x,y,p,v);
               }
            }
         }
         nd[v]=nd[v]+nd[w];
         //1.1.2
         if(lowpt[w]<lowpt[v])
         {
            lowpt2[v]=lowpt[v]; lowpt[v]=lowpt[w];
            low2[v]=low[v]; low[v]=low[w];
            firstIndx[v]=firstIndx[w];
            tolow[v]=w; 
         }
         //1.1.3
         else if(lowpt[w]<lowpt2[v])
         {
            lowpt2[v]=lowpt[w]; low2[v]=low[w];
            firstIndx[w]=-1;
         }
      }
      //1.2
      else 
      {
         if(dfs[w]<dfs[v] && w!=parent[v])
         {
            //1.2.1
            if(dfs[w]<=lowpt[v])
            {
               lowpt2[v]=lowpt[v]; lowpt[v]=dfs[w];
               low2[v]=low[v]; low[v]=w;
               firstIndx[v]=-1;
               tolow[v]=w;
            }
            else if(dfs[w]<lowpt2[v])
            {
               lowpt2[v]=dfs[w]; low2[v]=w;
            }
         }
      }
   }

   if(descend){stack_pointer++; continue;}   

   //2
   //2.1
   if(firstIndx[v]==-1)
   {   
      //2.1.1
      if(lowpt2[v]>lowpt[v])
      {
         push(v,v,tolow[v],low[v],low2[v]);
      }
   }
   //2.2
   else
   {
      int sp=firstIndx[v]*4;
      int x=STACK[sp];
      int y=STACK[sp+1];
      int p=STACK[sp+2];
      int q=STACK[sp+3];
      //2.2.1
      if(lowpt2[v]>dfs[q])
      {
         push(v,v,tolow[v],q,low2[v]);
      }
      //2.2.2
      else
      {
         while(firstIndx[v]!=-1 && lowpt2[v]<=dfs[p])
         {
            pop(v);
            if(firstIndx[v]!=-1)
            {
               sp=firstIndx[v]*4;
               x=STACK[sp];
               y=STACK[sp+1];
               p=STACK[sp+2];
               q=STACK[sp+3];            
            }         
         }
         if(firstIndx[v]!=-1 && lowpt2[v]<dfs[q])
         {
            push(v,x,y,p,low2[v]);
         }
      }
   } 

   //3
   for(int i=firstOut[v];i<firstOut[v+1]&&firstIndx[v]!=-1;i++)
   {
      int u=G[i];
      if(!(dfs[v]<dfs[u] && v!=parent[u])){continue;}
      int sp=firstIndx[v]*4;
      int x=STACK[sp];
      int y=STACK[sp+1];
      while(firstIndx[v]!=-1 && x==parent[y] && dfs[y]<=dfs[u] && dfs[u]<=dfs[y]+nd[y]-1)
      {
         pop(v);
         if(firstIndx[v]!=-1)
         {
            sp=firstIndx[v]*4;
            x=STACK[sp];
            y=STACK[sp+1];
         }
      }
   }

   stack_pointer--;
}

}

void insert_edge(int a, int b, char generator)
{
   if(generator)
   {
      if(a==parent[b])
      {
         if(!tree_edge_is_cutEdge[b])
         {

            cut_edges[2*n_cut_edges]=a;
            cut_edges[2*n_cut_edges+1]=b;
            n_cut_edges++;           
         }
         tree_edge_is_cutEdge[b]++;
      }
      else
      {
         if(!back_edge_is_cutEdge[a])
         {
            cut_edges[2*n_cut_edges]=a;
            cut_edges[2*n_cut_edges+1]=b;
            n_cut_edges++;  
         }
         back_edge_is_cutEdge[a]++;
      }
   }
   else
   {
      cut_edges[2*n_cut_edges]=a;
      cut_edges[2*n_cut_edges+1]=b;
      n_cut_edges++;
   }
}

void create_adj()
{
   G = (int*)malloc(sizeof(int)*4*m);
   firstOut = (int*)malloc(sizeof(int)*(n+1));
   for(int i=0;i<=n;i++){firstOut[i]=0;}
   for(int i=0;i<m;i++){firstOut[edges[2*i]+1]++; firstOut[edges[2*i+1]+1]++;}
   int* nextOut = (int*)malloc(sizeof(int)*(n+1));
   nextOut[0]=0;
   for(int i=1;i<=n;i++){firstOut[i]+=firstOut[i-1]; nextOut[i]=firstOut[i];}
   for(int i=0;i<m;i++)
   {
      int x=edges[2*i]; int y=edges[2*i+1];
      G[nextOut[x]++]=y;
      G[nextOut[y]++]=x;
   }
}










back to top