POJ 1236 强连通分量 Tarjan

好吧~图论的学习该告一段落了。这个题很有意思:

说有几个学校,相互传递盗版软件,为单向传递关系。问给最少几个学校盗版软件,可以使得全部的学校都有盗版软件。2问最少添加几个传递关系,使得不论城管消灭其中的一条传递线路,还是能够让所有的学校都通过一张盗版光盘传递完。

思路呢.... 很简单,对图中的强连通分量进行缩点,形成图G‘,这样去找入度为0的连通分量数即可。因为没有盗版软件必须要有源头,而如度为0的强连通分量没有源头,故发软件。

2.出度为零的连通分量和入度为零的强连通分量中值最大的即为答案。因为要连成环就不怕城管了,所以入度和出度为零的连边就好了~

求解强连通分量比较熟悉了~ 很快的写代码1Y

#include<iostream>
#include<stack>
#define MAXN 105
using namespace std;

struct Node
{
       int v;
       Node *next;
}Edge[MAXN*MAXN],*ptr[MAXN];

Node Edge2[MAXN];
Node *ptr2[MAXN];

int DFN[MAXN],LOW[MAXN];
int DEP,SCCNum;
int N,Point[MAXN];
bool inS[MAXN];
int min( int a,int b ){ return a<b?a:b; }

void addEdge( int u,int v )
{
     Node *p=&Edge[++DEP];
     p->v=v;
     p->next=ptr[u];
     ptr[u]=p;
}
void addEdge2( int u,int v )
{
     Node *p=&Edge2[++DEP];
     p->v=v;
     p->next=ptr2[u];
     ptr2[u]=p;
}

stack<int>myStack;
void Tarjan( int u )
{
     myStack.push(u);
     inS[u]=true;
     DFN[u]=LOW[u]=++DEP;
     Node *p=ptr[u];
     while( p )
     {
            if( DFN[p->v]==0 )
            {
                Tarjan( p->v );
                LOW[u]=min( LOW[u],LOW[p->v]);
            }
            else if( inS[p->v] )
                 LOW[u]=min(LOW[u],DFN[p->v] );
            p=p->next;
     }
     if( DFN[u]==LOW[u] )
     {
         int v;
         ++SCCNum;
         do
         {
               v=myStack.top();
               myStack.pop();
               inS[v]=0;
               Point[v]=SCCNum;
         }while( u!=v );
     }
}

int main()
{
    while( scanf( "%d",&N )!=EOF )
    {
           memset( DFN,0,sizeof(DFN) );
           memset( LOW,0,sizeof(LOW) );
           memset( inS,0,sizeof(inS) );
           memset( Point,0,sizeof(Point) );
           SCCNum=0;
           int i,j;
           for( i=0;i<=N;i++ )
                ptr[i]=ptr2[i]=NULL;
           
           DEP=0;
           for( i=1;i<=N;i++ )
           {
                while( true ){
                       scanf( "%d",&j );
                       if( j==0 )
                           break;
                       addEdge( i,j );
                }
           }
           DEP=0;
           for( i=1;i<=N;i++ )
                if( DFN[i]==0 )
                    Tarjan( i );
           DEP=0;
           for( i=1;i<=N;i++ )
           {
                Node *p=ptr[i];
                while( p )
                {
                       if( Point[i]!=Point[p->v] )
                           addEdge2( Point[i],Point[p->v] );
                       p=p->next;
                }
           }
           int inD[MAXN],outD[MAXN];
           memset( inD,0,sizeof(inD) );
           memset( outD,0,sizeof(outD) );
           for( i=1;i<=SCCNum;i++ )
           {
                Node *p=ptr2[i];
                while( p )
                {
                       outD[i]++;
                       inD[p->v]++;
                       p=p->next;
                }
           }
           int cntI,cntO;
           cntI=cntO=0;
           //printf( "%d\n",SCCNum );
           for( i=1;i<=SCCNum;i++ )
           {
                if( inD[i]==0 )
                    cntI++;
                if( outD[i]==0 )
                    cntO++;
           }
           printf( "%d\n",cntI );
           if( SCCNum==1 )
               printf( "0\n" );
           else
               printf( "%d\n",cntI>cntO?cntI:cntO );
    }
    return 0;
}


你可能感兴趣的:(null)