我的点双连通模板(HDU2242)

http://acm.hdu.edu.cn/showproblem.php?pid=2242

const   int  Max_N = 10008 ;
const   int  Max_M = 20008 ;

struct  Edge{
        int u ;
        int v ;
        int next ;
}edge[Max_M*4];

int id ;
int List[Max_N]  , List2[Max_N] ;

void add_edge(int u , int v ){
     edge[id].u = u ;
     edge[id].v = v ;
     edge[id].next = List[u] ;
     List[u] = id++ ;
}

void add_edge2(int u , int v){
     edge[id].u = u ;
     edge[id].v = v ;
     edge[id].next = List2[u] ;
     List2[u] = id++ ;
}

int  val[Max_N] , sumall , sum[Max_N]  , dp[Max_N] ;
/*belong[u] , u所在的双连通分量 , color双连通分量个数 */
/*同一个belong[]里的任意2点至少有2条不同的路径*/
int   dfsn[Max_N] , low[Max_N] , Time , color  , belong[Max_N] ;
stack <int> Q ;
void  tarjan(int u , int father){
      int v , e ,  flag = 1 ;
      dfsn[u] = low[u] = ++Time ;
      Q.push(u) ;
      for(e = List[u] ; e != -1 ; e = edge[e].next){
             v = edge[e].v ;
             if(v == father && flag){  //重边
                   flag = 0 ;
                   continue ;
             }
             if(!dfsn[v]){
                   tarjan(v , u) ;
                   low[u] = min(low[u] , low[v]) ;
             }
             else
                   low[u] = min(low[u] ,dfsn[v]) ;
      }
      if(dfsn[u] == low[u]){
             color++ ;
             do{
                   v = Q.top() ;
                   Q.pop() ;
                   belong[v] = color ;
                   sum[color] += val[v] ;
             }while(u != v) ;
      }
}

int  N , M ;

void Init(){
     id = color = sumall = Time = 0 ;
     memset(sum , 0 ,sizeof(sum)) ;
     memset(dfsn , 0 , sizeof(dfsn)) ;
     memset(List , -1 , sizeof(List)) ;
     memset(List2 , -1 , sizeof(List2)) ;
     memset(dp , 0 , sizeof(dp)) ;
}

int  ans ;

void dfs(int u , int father){
     dp[u] = sum[u] ;
     int e , v ;
     for(e = List2[u] ; e != -1 ; e = edge[e].next){
           v = edge[e].v ;
           if(v == father)
               continue ;
           dfs(v , u) ;
           dp[u] += dp[v] ;
           ans = min(ans , abs(sumall - 2 * dp[v])) ;
     }
}


int  main(){
     int i , u , v , e ;
     while(cin>>N>>M){
          Init() ;
          for(i = 1 ; i <= N ; i++){
               scanf("%d" ,&val[i]) ;
               sumall += val[i] ;
          }
          for(i = 1 ; i <= M ; i++){
               scanf("%d%d" ,&u ,&v) ;
               u++ , v++ ;
               add_edge(u , v) ;
               add_edge(v , u) ;
          }
          for(i = 1 ; i <= N ; i++){
               if(!dfsn[i])
                   tarjan(i , -1) ;
          }
          if(color == 1){
               puts("impossible") ;
               continue ;
          }
          for(i = 1 ; i <= N ; i++){
               for(e = List[i] ; e != -1 ; e = edge[e].next){
                    u = edge[e].u ;
                    v = edge[e].v ;
                    if(belong[u] != belong[v])
                        add_edge2(belong[u] , belong[v]) ;
               }
          }
          ans = 1<<30 ;
          dfs(1 , -1) ;
          cout<<ans<<endl ;
     }
     return 0 ;
}


你可能感兴趣的:(我的点双连通模板(HDU2242))