toj 2233

toj 2233
from roba

找出强联通分量,然后求出缩点图,找出缩点图内出度为0的点内的原顶点最小的cost值累加

(关于强联通分量前面有文章介绍)

#include  < stdio.h >
#include 
< string .h >
const   int  N  =   10001 ;
const   int  M  =   200001 ;
struct  e{
    
int  v;
    e
*  next;
};
e
*  link[N], edge[M],  * tlink[N], tedge[M];
int  n, m, cost[N], el, tel, f[N], time, belon[N], degree[N], s[N], ans[N];
bool  judge[N], zero[N];
void  dfs( int  v){
    
int  i;e *  l  =  link[v];judge[v]  =   true ;
    
while (l){
        
if ( ! judge[l -> v])dfs(l -> v);
        l 
=  l -> next;
    }f[v] 
=  time ++ ;
}
void  tdfs( int  v,  int  p){
    
int  i;e *  l  =  tlink[v];judge[v]  =   true ;belon[v]  =  p;
    
while (l){
        
if ( ! judge[l -> v])tdfs(l -> v, p);
        l 
=  l -> next;
    }
}
int  main(){
    freopen(
" 2233.in " " r " , stdin);
    freopen(
" 2233.out " " w " , stdout);
    
int  i, j, u, v, fl,  out ;e *  l;
    
while (scanf( " %d%d " & n,  & m), m  ||  n){
        
for (i  =  time  =   0 ; i  <  n; i ++ ){tlink[i]  =  link[i]  =  NULL;judge[i]  =  degree[i]  =  zero[i]  =   0 ;ans[i]  =   0x7fffffff ;}
        
for (i  =   0 ; i  <  n; i ++ )scanf( " %d " & cost[i]);
        
for (el  =  tel  =   0 , i  =   0 ; i  <  m; i ++ ){
            scanf(
" %d%d " & u,  & v);u -- ;v -- ;
            edge[el].v 
=  v;edge[el].next  =  link[u];link[u]  =   & edge[el ++ ];
            tedge[tel].v 
=  u;tedge[tel].next  =  tlink[v];tlink[v]  =   & tedge[tel ++ ];
        }
        
for (i  =   0 ; i  <  n; i ++ ) if ( ! judge[i])dfs(i);
        
for (i  =   0 ; i  <  n; i ++ )s[f[i]]  =  i;
        memset(judge, 
0 sizeof (judge));fl  =   0 ;
        
for (i  =  n  -   1 ; i  >=   0 ; i -- ){
            
if ( ! judge[s[i]]){
                tdfs(s[i], fl
++ );
            }
        }
        
for (i  =   0 ; i  <  n; i ++ ){
            l 
=  link[i];
            
while (l){
                
if (belon[i]  !=  belon[l -> v])degree[belon[l -> v]] ++ ;
                l 
=  l -> next;
            }
        }
        
for (i  =   0 ; i  <  fl; i ++ ){ if ( ! degree[i]){zero[i]  =   true ;}}
        
for (i  =   0 ; i  <  n; i ++ ){
            
if (zero[belon[i]]){
                
if (cost[i]  <  ans[belon[i]])ans[belon[i]]  =  cost[i];
            }
        }
out   =   0 ;
        
for (i  =   0 ; i  <  n; i ++ ){
            
if (zero[i]) out   +=  ans[i];
        }
        printf(
" %d\n " out );
    }
    
return   0 ;
}


你可能感兴趣的:(toj 2233)