Strongly connected components spree

Strongly connected components spree

The main problem with some basic questions have to strongly connected component of the graph
incrementally difficult, but all the water

[USACO06JAN] cow The Cow Prom Prom

[Problem of]

John N (2 <= N <= 10,000) cows very excited, because this is the prom night! They put on a new dress and shoes, do the flowers, they have to perform a round dance.
Only cows can show such a round dance. Round dance requires some rope and a round of pool. Cows around the pool stand, clockwise numbered sequentially from 1 to N. each cow will face the pool, so that she could see each other cows.
holding on to dance this dance circle, they found a rope M several cows hooves one end of the rope, the rope clockwise direction bypassing the tank, the other end tied to the cow others. Thus, some of the dairy cow can be pulled other cows Some cows may hold many rope, a rope may also have some cows no
for a cow, for example, Bessie, her round dance is successful, it can be tested: pull her along the rope, pulling her to find the cow, and then only along the tow rope cows, has found a towed cows, and so on, if eventually returned to Bessie, then danced round her success, because cows on a ring that can rotate counterclockwise traction and danced round dance. If such a test unable Into, that her round dance is unsuccessful.
If the two successful jump circle dance cows have attached a rope, that they may belong to the same combination.
A description is given of each rope, find, successfully jumped round dance how many cows combination?

[Thinking]

Template problem, we just count the number of points greater than the strongly connected component 1 can be.

[Code]

#include<bits/stdc++.h>
using namespace std;
const int  MAXN = 50005 ;
inline  int  read(){
    int s = 0 ; char g=getchar() ;while(g>'9'||g<'0')g=getchar() ;
    while(g>='0'&&g<='9')s=s*10+g-'0',g=getchar();return s ;
}
int head[ MAXN ] , to[ MAXN*2 ] , nex[ MAXN*2 ] , tot = 1 ;
int dfn[ MAXN ] , low[ MAXN ] , num = 0 , scc[ MAXN ];
int  N , M , root , kind = 0 ;
bool used[ MAXN ] ;
stack<int>q ; 
void  add( int x , int  y  ){
    to[ ++tot ] = y , nex[ tot ] = head[ x ] , head[ x ] = tot ;
}
void  tarjan( int u ){
    dfn[ u ] = low[ u ] = ++num ; used[ u ] =true ; 
    q.push( u ) ;
    int  flag = 0 ;
    for( int i = head[ u ] ; i ; i = nex[ i ] ){
        if( !dfn[ to[ i ] ] ){
            tarjan( to[ i ] ) ;
            low[ u ] = min( low[ u ] , low[ to[ i ] ] ) ;
        }
        else if( used[ to[ i ] ] ) low[ u ] = min ( low[ u ] ,dfn[ to[ i ] ] ) ;
    }
    if( low[ u ] == dfn[ u ] ){
        kind++ ;
        int  now = -1 ;
        while( now != u ){
            now = q.top() ; q.pop() ;
            used[ now ] = false ; 
            scc[ kind ]++ ;
        }
    }
}
int main(){
    N = read() , M = read() ;
    int  m1 , m2 ;
    for( int i = 1 ; i <= M ; ++i ){
        m1 = read() , m2 = read() ; if( m1 == m2 )continue ;
        add( m1 , m2 ) ;
    }
    for( int i = 1 ; i <= N ; ++i )
        if( !dfn[ i ] )root = i , tarjan( i ) ;
    int ans = 0 ;
    for( int i = 1 ; i <= kind ; ++i )
        if( scc[ i ] > 1 )ans++ ;
    cout<<ans ;
    return 0 ;
}

[HAOI2006] popular cattle

[Problem of]

Each cow dreams of becoming a star in the bullpen. Like all cows are cows cow is a star. All cows are the narcissists per cow always like to own.

Between cow "like" can pass - if A like B, B like C, the A like C. A total of N cowshed cows given love relationship between the number of cows.

You calculate how many cows can become a star.

[Thinking]

After the template question 2, we consider the reduction point, after recording a contraction of points is the number of sum zero point, Category talk

This is the number of China Unicom strong component of the midpoint of the sum == 1 || sum> 1 obviously does not exist sum == 1 answer

[Code]

#include<bits/stdc++.h>
using namespace std;
const int  MAXN = 50005 ;
inline  int  read(){
    int s = 0 ; char g=getchar() ;while(g>'9'||g<'0')g=getchar() ;
    while(g>='0'&&g<='9')s=s*10+g-'0',g=getchar();return s ;
}
int head[ MAXN ] , to[ MAXN*2 ] , nex[ MAXN*2 ] ;
int dfn[ MAXN ] , low[ MAXN ] , scc[ MAXN ] , number[ MAXN ] , ans[ MAXN ] ;
int  N , M , kind , num , tot = 1 ;
bool used[ MAXN ] ;
stack<int>q ; 
void  add( int x , int  y  ){
    to[ ++tot ] = y , nex[ tot ] = head[ x ] , head[ x ] = tot ;
}
void  tarjan( int u ){
    dfn[ u ] = low[ u ] = ++num ; used[ u ] =true ; 
    q.push( u ) ;
    int  flag = 0 ;
    for( int i = head[ u ] ; i ; i = nex[ i ] ){
        if( !dfn[ to[ i ] ] ){
            tarjan( to[ i ] ) ;
            low[ u ] = min( low[ u ] , low[ to[ i ] ] ) ;
        }
        else if( used[ to[ i ] ] ) low[ u ] = min ( low[ u ] ,dfn[ to[ i ] ] ) ;
    }
    if( low[ u ] == dfn[ u ] ){
        kind++ ;
        int  now = -1 ;
        while( now != u ){
            now = q.top() ; q.pop() ;
            used[ now ] = false ; 
            number[ kind ]++ ; scc[ now ] = kind ;
        }
    }
}
int main(){
    N = read() , M = read() ;
    int  m1 , m2 ;
    for( int i = 1 ; i <= M ; ++i ){
        m1 = read() , m2 = read() ; if( m1 == m2 )continue ;
        add( m1 , m2 ) ;
    }
    for( int i = 1 ; i <= N ; ++i )
        if( !dfn[ i ] )tarjan( i ) ;
    int anss = 0 ;
    for( int u = 1 ; u <= N ; ++u )
        for( int i = head[ u ] ; i ; i = nex[ i ] ){
            if( scc[ u ] != scc[ to[ i ] ] )ans[ scc[ u ] ]++ ;
        }
    for( int i = 1 ; i <= kind ; ++i )
        if( !ans[ i ] )anss++ ;
    if( anss > 1 || anss == 0 ){cout<<0;return 0;}
    for( int i = 1 ; i <= kind ; ++i )
        if( !ans[ i ] ){ anss = number[ i ] ; break ; }
    cout<<anss ;
    return 0 ;
}

[USACO5.3] Campus Network Network of Schools

[Problem of]

Some schools even into a computer network. Those schools have entered into an agreement: each school will give some other school distribution software (referred to as "receiving schools"). Note that the list even if the B school in the distribution list A, A is not necessarily in the B-school's.

You want to write a program to calculate, according to the agreement, in order to make the network all schools use the new software, new schools must accept a minimum number of copies of the Software (subtasks A). Furthermore, we wanted to determine through a school to send any new software, which will be distributed to all schools in the network. To accomplish this task, we may have to expand the school to receive lists to new members. Calculate the minimum necessary to increase the number of extensions that make us no matter which school to send new software, it will reach all the remaining schools (subtasks B). An extension is the introduction of a new member in the school receives a school list.

Input Format

The first line of the input file comprises an integer N: the number of school network (2 <= N <= 100). Schools identified by the first N positive integers.

The next N lines each line representing a school receives a list (distribution list). I + 1-i row comprises receiving an identifier of the school school. Each list ends with 0. Only empty list is represented by a 0.

Output Format

Your program should output two lines in the output file.

The first line should contain one positive integer: A solution of sub-tasks.

Solution of the task B of the second line should be included.

[Thinking]

Consider subtasks A:

We found that, after shrinking point, if there is still a point (strongly connected components) into the reading is zero, then the point (strongly connected components) necessarily require a copy of the software, but also to all of the above points copies of the software, the other point It will be obtained from existing edges.

So the answer is subtasks A point reduction after admission to the edge of 0.

In consideration of sub-tasks B:

We take a picture bordered addition strong graph (strongly connected component is not great), we consider the original point is not satisfied must be strongly connected graph condensing point after admission to 0 or a 0 degree point. Consider: 1. If there is a simultaneous admission of 0 and the point A to the point B of this point is 0, then the optimal strategy must be connected to the A side from the B.
2. If the point A alone, from any point of the connection point A side reversion to, point B alone, we only need to let the connection to a reversion from the B side begins.
Continuously performing the above procedure, operation a priority, followed by the second operation, each operation can be transformed into a secondary original problem (fewer edges to be connected). It should be possible to obtain a great strong graph.

Special case, if the picture is a strongly connected component, 0 is output directly.

[Code]

#include<bits/stdc++.h>
using namespace std; 
const int MAXN = 10005 ;
inline int read(){
    int s=0 ; char g=getchar() ; while( g>'9'||g<'0' )g=getchar() ;
    while( g>='0'&&g<='9')s=s*10+g-'0',g=getchar() ; return s ;
}
int  to[ MAXN ] , nex[ MAXN ] , head[ 105 ] , tot = 1 , num , kind ; 
int  N , M , dfn[ 105 ] , low[ 105 ] , scc[ 105 ] , number[ 105 ] , du[ MAXN ] , du2[ MAXN ]; 
bool vis[ MAXN ] ;
stack<int>q ;
void  add( int x , int y ){
    to[ ++tot ] = y , nex[ tot ] = head[ x ] , head[ x ] = tot ; 
}
void  tarjan( int u ){
    dfn[ u ] = low[ u ] = ++num ; vis[ u ] = true ;
    q.push( u ) ;
    for( int i = head[ u ] ; i ; i = nex[ i ] )
        if( !dfn[ to[ i ]  ] ){
            tarjan( to[ i ] ) ;
            low[ u ] = min( low[ u ] , low[ to[ i ] ] ) ;
        }
        else if( vis[ to[ i ] ] )low[ u ] = min( low[ u ] , dfn[ to [ i ] ] ) ;
    if( low[ u ] == dfn[ u ] ){
        kind++ ; int now = -1 ; 
        while( now != u ){
            now = q.top() ; q.pop() ;
            vis[ now ] = false ; 
            number[ kind ]++ , scc[ now ] = kind ; 
        }
    }
}
int main(){
    N =  read() ; int m1 ;
    for( int i = 1 ; i <= N ; ++i ){
        while(true){
            m1 = read() ;if( !m1 )break ; 
            add( i , m1 ) ;
        }
    }
    for( int i = 1 ; i <= N ; ++i )
        if( !dfn[ i ] )tarjan( i ) ;
    for( int u = 1 ; u <= N ; ++u )
        for( int i = head[ u ] ; i ; i = nex[ i ] )
            if( scc[ u ] != scc[ to[ i ] ] )du[ scc[ to[i] ] ]++ , du2[ scc[ u ] ]++ ;
    int ans = 0 , ans2 = 0 ; 
    for( int i = 1 ; i <= kind ; ++i ){
        if( !du[ i ] )ans++;
        if( !du2[ i ] )ans2++ ;
    }
    cout<<ans<<endl;
    if( kind == 1 )cout<<0 ; //注意特判 
    else cout<<max(ans,ans2) ;
    return 0 ;  
}

Guess you like

Origin www.cnblogs.com/ssw02/p/11515086.html