zoukankan      html  css  js  c++  java
  • poj 3694 Network(边双连通+LAC)

    题意:一个网络中有N台电脑,M条线路,现在任意两台电脑都可以互相通信,但是有些线路是重要的,如果破坏了他们,那么这个网络就不连通了,我们称这样的线路为“桥”,如果向网络中加入一些线路,问加入线路后的网络中有多少“桥”。

    思路:先求出强连通分支,缩点形成一个树,如果加入线路的两点在同一分支中,那么这条线路就没什么用了,直接输出cnt就可以了,如果这两点不在同一分支中,那么就相当于向一根树中加入一条边,然后将从这两点到他们最近公共祖先的线路都去掉就是现在网络中的“桥”的数量。这题不限时间,LAC用最原始的方法都能过,因为对LAC的两种求法都不太熟悉,所以就用了最原始的方法。

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <math.h>
    #define  N 100005
    #define  M 200005
    using namespace std ;
    
    struct node
    {
        int e , next ;
    }p[2*M+1000] ;
    
    int head[N] , dfn[N] , low[N] , vist[N] , pre[N] ;
    bool mark[N] ;
    int n , m , num , cnt , id , q ;
    
    void add( int x , int y )
    {
        p[num].e = y ;
        p[num].next = head[x] ;
        head[x] = num++ ;
    
        p[num].e = x ;
        p[num].next = head[y] ;
        head[y] = num++ ;
    }
    
    void dfs( int x )
    {
        vist[x] = 1 ;
        dfn[x] = low[x] = ++id ;
        for ( int i = head[x] ; i != -1 ; i = p[i].next )
        {
            int v = p[i].e ;
            if( !vist[v] )
            {
                pre[v] = x ;
                dfs( v ) ;
                low[x] = min( low[x] , low[v] ) ;
                if ( low[v] > dfn[x] )//map[x][v]就是桥
                {
                    cnt++ ;
                    mark[v] = true ;
                }
            }
            else if ( vist[v] && v != pre[x] )
            low[x] = min( low[x] , dfn[v] ) ;
        }
        //vist[x] = 2 ;
    }
    
    void find( int x , int y )
    {
        while( dfn[x] > dfn[y] )
        {
            if ( mark[x] )
            {
                cnt-- ;
                mark[x] = false ;
            }
            x = pre[x] ;
        }
        while ( dfn[y] > dfn[x] )
        {
            if ( mark[y] )
            {
                cnt-- ;
                mark[y] = false ;
            }
            y = pre[y] ;
        }
        while ( x!= y )
        {
            if ( mark[x] )
            {
                cnt-- ;
                mark[x] = false ;
            }
            if ( mark[y] )
            {
                cnt-- ;
                mark[y] = false ;
            }
            x = pre[x] ;
            y = pre[y] ;
        }
    }
    
    int main()
    {
        int i , x , y ;
        int cas = 1 ;
    
        //freopen( "input.txt" , "r" , stdin ) ;
        while ( scanf ( "%d%d" , &n , &m ) , n + m )
        {
            memset( head , -1 , sizeof( head )) ;
            num = 0 ;
            for ( i = 1 ; i <= m ; i++ )
            {
                scanf ( "%d%d" , &x , &y ) ;
                add( x , y ) ;
            }
            memset( dfn , 0 , sizeof ( dfn )) ;
            memset( low , 0 , sizeof ( low )) ;
            memset( vist , 0 , sizeof ( vist )) ;
            memset( mark , false , sizeof ( mark )) ;
            //求强连通,缩点
            cnt = id = 0 ;
            for ( i = 1 ; i <= n ; i++ )
            if ( !dfn[i] )
            dfs( i );
    
            scanf ( "%d" , &q );
            printf ( "Case %d:\n" , cas++ ) ;
            while ( q-- )
            {
                scanf ( "%d%d" , &x , &y ) ;
                //两点是否在同一分支中
                if ( low[x] == low[y] )
                {
                    printf ( "%d\n" , cnt ) ;
                    continue ;
                }
                //求公共最近祖先
                find ( x , y );
                printf ( "%d\n" , cnt ) ;
            }
            printf ( "\n" ) ;
        }
        return 0 ;
    }
  • 相关阅读:
    善用VS中的Code Snippet来提高开发效率
    c#获取远程文件更新时间
    图解VS2008单元测试及查看代码覆盖率
    常用关于 JavaScript 中的跨域访问方法
    Jquery中使用setInterval和setTimeout
    外链图片也有风险吗?
    设计模式学习总结抽象工厂模式(Abstract Factory Pattern)
    斐波拉杰博弈 取石子(五)
    后缀表达式 NYOJ 257
    杭电 1085 Holding BinLaden Captive!
  • 原文地址:https://www.cnblogs.com/misty1/p/2772180.html
Copyright © 2011-2022 走看看