Smile

Smile

常用链接

统计

最新评论

hnu第一场 Equivalent Sets 强连通分量 添加边使其成为一个强连通分量

考察知识点:强连通分量的的求法
bug:注意强连通分量个数只有一个的情况
思维:这个转化倒是知道,但是知识点不足,还有一个更重要的是邻接表的写法和邻接矩阵的写法有很多的不同,特别是在第二次dfs的时候注意元素的表示不是i了而应该是
for( int i= 0; i<num; ++i)
       if( flag[ b[cur][i] ] == 0  )
          visttwo(b[cur][i],sig);
再贴一个tyvj的纯裸的强连通分量:tvvj1111
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define  max 210
int a[max][max],b[max][max];//a为图G的邻接矩阵,b为图G的反图的邻接矩阵
int  bleg[max];
int flag[max];
int numb[max];
int n;
void vistone(int cur,int &sig)
{
     flag[cur] = 1;
     for( int i=1; i<=n; ++i)
         if( flag[i] == 0 && a[cur][i] == 1 )
          vistone(i,sig );
     numb[++sig] = cur;
}
void visttwo( int cur ,int sig)
{
     flag[cur] = 1;
     bleg[cur] =sig;
     for( int i= 1; i<=n; ++i)
       if( flag[i] == 0 && b[cur][i] == 1 )
          visttwo(i,sig);
}     
int korareju()
{
    int sig =0;
    memset(flag,0,sizeof(flag));
    for( int i=1;i<=n; ++i)
       if( flag[i] == 0)
           vistone(i,sig);
    memset(flag,0,sizeof(flag));
    sig=0;
    for(int i=n; i>=1; --i )
       if( flag[ numb [i] ] == 0 )
       {
           visttwo(numb[i], (++sig) );
       }
    return sig;
}
int main()
{
    scanf("%d",&n);
    int i = 0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    while( (i++)<n )
    {
       while( true )
       {
           int x;
           scanf("%d",&x);
           if( x == 0)
              break;
           a[i][x] = 1;
           b[x][i] = 1;
       }
    }
    int w = korareju();
    printf("%d\n",w);
    return 0;
}
   


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
#define  max 20010
vector< int > a[max],b[max];//a为图G的邻接矩阵,b为图G的反图的邻接矩阵
int  bleg[max];
int flag[max];
int numb[max];
int out[max];
int in[max];
int n;
void vistone(int cur,int &sig)
{
     flag[cur] = 1;
     int num = a[cur].size();
     for( int i=0; i<num; ++i)
         if( flag[ a[cur][i] ] == 0 )
              vistone(a[cur][i],sig );
     numb[++sig] = cur;
}
void visttwo( int cur ,int sig)
{
     flag[cur] = 1;
     bleg[cur] =sig;
     int num = b[cur].size();
     for( int i= 0; i<num; ++i)
       if( flag[ b[cur][i] ] == 0  )
          visttwo(b[cur][i],sig);
}     
int korareju()
{
    int sig =0;
    memset(flag,0,sizeof(flag));
    for( int i=1;i<=n; ++i)
       if( flag[i] == 0)
           {
             vistone(i,sig);
           }
    memset(flag,0,sizeof(flag));
    sig=0;
    for(int i=n; i>=1; --i )
       if( flag[ numb[i] ] == 0 )
       {
           visttwo( numb[i], (++sig) );
       }
    return sig;
}
int main()
{
    int m;
    while( scanf("%d%d",&n,&m) == 2 )
   {
    int k = 0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(numb,0,sizeof(numb));
    memset(out,0,sizeof(out));
    memset(in,0,sizeof(in));
    memset(bleg,0,sizeof(bleg));
    while( (k++)<m )
    {
           int x,y;
           scanf("%d%d",&x,&y);
           a[x].push_back(y);
           b[y].push_back(x);
    }
    if( n <= 1 )
    {
        printf("0\n");
        continue;
    }
    int w = korareju();
    if( w == 1 )
    {
        printf("0\n");
        continue;
    }
    for( int i=1; i<=n; ++i )
    {
      int num = a[i].size();
      for(int j=0; j<num; ++j)
         if( bleg[i] != bleg[ a[i][j] ] )
         {
             out[bleg[i]]++;
             in[ bleg[ a[i][j] ] ]++;
         }
    }
    int od=0;
    int id=0;
    for( int i= 1; i<=w; ++i)
    {
       if( out[i] == 0 )
          od++;
       if( in[i] == 0 )  
          id++;
    }
    int max0=od;
    if(max0<id)
      max0=id;   
    printf("%d\n",max0);
   }
    return 0;
}

posted on 2011-07-15 17:22 Smile3 阅读(123) 评论(0)  编辑 收藏 引用 所属分类: 多校联赛题解模板