LA 5135 Mining Your Own Business

来源:互联网 发布:linux解析文件 编辑:程序博客网 时间:2024/06/03 05:29
这是一个bcc题目 。
建图模型是:在一个无向图上 , 选择尽量少的点涂黑 , 使得任意删除一个点 , 每个连通分量都至少有一个黑点 。

所有 ,  可以发现 , 如果把割点涂黑是不划算的 。 因此有两种方法。
1、用dfs求出所以割点 , 然后再用bfs进行遍历(不能经过割点) , 每次遍历出一个连通图 , 如果这个图只有1个割点 ,那么标记一个 , 如果超过1个黑点, 就不要标记 , 因为 , 每次只删除 一个割点 , 所有当这个连通图连接了两个割点时 ,就一点可以到达其他黑点 。 而如果整个图都没有黑点 , 则不需要遍历 , 可知只有2个黑点 。
2、先求出这个图中的所有bcc , 就判断每个bcc , 如果这个bcc只有1个割点 , 那就要标记1个黑点 ,其他的则不需要进行标记 。

代码 :
1、
#include
#include
#include
#include
using namespace std ;

const int MAXN = 200100;
vectorgrap[MAXN] ;
int pre[MAXN] , iscut[MAXN];
int n = 0, m = 0, dfs_clock = 0;
int bz[MAXN] , d = 0 , f = 1 , bz2[MAXN];

int dfs(int u ,int  fu)
{
    int lowu =pre[u] = ++dfs_clock;
    int child =0;
    for(int i =0 ; i < grap[u].size() ; i++)
    {
       int v =grap[u][i] ;
      if(!pre[v])
       {
          child +=1;
          int lowv =dfs(v , u);
          if(lowv <lowu)  lowu = lowv;
          if(lowv>= pre[u])
          {
             iscut[u] =1;
             d +=1;
             bz[u] =1;
          }
       }
       elseif(pre[v] < pre[u] && v != fu)
       {
          if(pre[v]< lowu)
             lowu =pre[v];
       }
    }
    if( fu <0 && child == 1)
    {
       if(iscut[u]== 1)
       {
          d -=1;
          iscut[u] = 0;
          bz[u] =0;
       }
    }
    returnlowu;
}

void dfs_find(int u)
{

    for(int i =0 ; i < grap[u].size() ; i++)
    {
       int v =grap[u][i];
       if(bz2[v]==0&& iscut[v])
       {
          d +=1;
          bz2[v] = 1;
       }
       if(bz[v] ==0)
       {
          f +=1;
          bz[v] =1;
         dfs_find(v);
       }
    }
}

int main()
{
    int p =1;
   while(scanf("%d" , &n) != EOF)
    {
      if(!n)  break ;
       inti  , x , y , j;
       for(i = 1; i<= m; i++)
         grap[i].clear();
       m = 0;
       for(i = 0 ;i < n; i++)
       {
          scanf("%d%d" , &x , &y);
         grap[x].push_back(y);
         grap[y].push_back(x);
          if(x <y)  x = y;
          if(x >m)  m = x;
       }
      
       memset(pre ,0 , sizeof(pre));
       memset(iscut, 0 , sizeof(iscut));
       memset(bz ,0 , sizeof(bz));
       dfs_clock =0 ;
       d = 0;

       dfs(1 ,-1);

       long longmin = 0 , sum = 1;
       if(d ==0)
       {
          printf("Case%d: %lld %lld\n" , p++ , 2 ,(long long)m*(m-1)/2);
       }
       else
       {
          for(i = 1; i<= m; i++)
          {
            if(!bz[i])
             {
                memset(bz2 ,0 , sizeof(bz2));
                f = 1;
                d = 0;
                bz[i] =1;
               dfs_find(i);
                if(d <=1)
                {
                   min +=1;
                   sum *=(longlong)f;
                }
             }
          }
          printf("Case%d: %lld %lld\n" , p++ , min , sum);
       }
    }
    return0;
}

2、

#include
#include
#include
#include
#include
using namespace std;

const int MAXN =200100 ;
vectorgrap[MAXN] , bcc[MAXN];
int pre[MAXN] , iscut[MAXN];
int dfs_clock = 0, dfs_cut = 0, bccno[MAXN];
int n , m = 0;
stacks , t ;

int dfs(int u , int fu)
{
    int lowu =pre[u] = ++dfs_clock;
    int child =0;
    for(int i =0 ; i < grap[u].size() ; i++)
    {
      
       int v =grap[u][i];
      if(!pre[v])
        
         s.push(u);
         t.push(v);
         child++;
          int lowv =dfs(v , u);
          if(lowv <lowu)
          lowu =lowv;
          if(lowv>= pre[u])
          {
             iscut[u] =1;
             dfs_cut++;bcc[dfs_cut].clear();
             for(;;)
             {
                int x =s.top() , y = t.top(); s.pop() ; t.pop();
                if(bccno[x]!= dfs_cut)  {bcc[dfs_cut].push_back(x) ; bccno[x]= dfs_cut;}
                if(bccno[y]!= dfs_cut)  {bcc[dfs_cut].push_back(y) ; bccno[y]= dfs_cut;}
                if(x == u&& y == v)  break;
             }
          }
       }
       elseif(pre[v] < pre[u] && v != fu)
       {
          s.push(u);t.push(v);
          if(lowu >pre[v])
          lowu=  pre[v];
       }
    }
    if(fu < 0&& child == 1)  iscut[u] = 0;
    returnlowu;
}

int main()
{
    int p =1;
   while(scanf("%d" , &n) != EOF)
    {
      if(n==0)  break;
       int i ,j , x, y;
       for(i = 1; i<= m ; i++)
         grap[i].clear();
       m = 0;
       for(i = 0 ;i < n; i++)
       {
          scanf("%d%d" , &x , &y);
         grap[x].push_back(y);
         grap[y].push_back(x);
          if(x <y)  x = y;
          if(m <x)  m = x;
       }
       dfs_clock =dfs_cut = 0;
       memset(bccno, 0 , sizeof(bccno));
       memset(pre ,0 , sizeof(pre));
       memset(iscut, 0 , sizeof(iscut));
       dfs(1 ,-1);
       int ans1 = 0, ans2 = 1;
       for(i = 1; i<= dfs_cut; i++)
       {
          int cut_cnt= 0;
          for(j = 0 ;j < bcc[i].size() ; j++)
            if(iscut[bcc[i][j]])  cut_cnt += 1;
          if(cut_cnt== 1) 
          {
             ans1 +=1;
             ans2*=(bcc[i].size() - cut_cnt) ;
          }
       }
       if(dfs_cut== 1)
       {
          ans1 =2;
          ans2=bcc[1].size()*(bcc[1].size()-1)/2 ;
       }
       printf("Case%d: %lld %lld\n" , p++ , ans1 , ans2);
    }
    return0;
}
0 0