我的点双连通模板(HDU2242)

来源:互联网 发布:角平分线逆定理己知 编辑:程序博客网 时间:2024/05/10 10:23

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 ;}


0 0
原创粉丝点击