HDU 3861 The King’s Problem

HDU 3861 The King’s Problem
题目大意:给出一个有向图,问最多能够分成多少个区域,使得每个区域内的任意一对顶点X、Y间,要么X能达到Y,要么Y能到达X。
不错的题目!
具体做法是这样的,因为强连通分量内部的点肯定能互相到达,因此先缩点;然后问题就转化成了有向无环图的最小路径覆盖问题,因为缩点之后的图上的任意一条路径都是满足要求的。
以下是我的代码:
/*
 * Author:  lee1r
 * Created Time:  2011/8/15 11:04:01
 * File Name: hdu3861.cpp
 
*/
#include
< iostream >
#include
< sstream >
#include
< fstream >
#include
< vector >
#include
< list >
#include
< deque >
#include
< queue >
#include
< stack >
#include
< map >
#include
< set >
#include
< bitset >
#include
< algorithm >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
#include
< cctype >
#include
< cmath >
#include
< ctime >
#define  L(x) ((x)<<1)
#define  R(x) (((x)<<1)+1)
#define  Half(x) ((x)>>1)
#define  Lowbit(x) ((x)&(-(x)))
using   namespace  std;
const   int  kInf( 0x7f7f7f7f );
const   double  kEps(1e - 8 );
typedef unsigned 
int   uint ;
typedef 
long   long  int64;
typedef unsigned 
long   long  uint64;

const   int  kMaxn( 5007 );
const   int  kMaxm( 100007 );

struct  Edge
{
    
int  u,v;
};
int  N,M,cnt,first2[kMaxn],next2[kMaxm],e2[kMaxm];
int  n,dfscnt,dfsn[kMaxn],low[kMaxn],id[kMaxn];
stack
< int >  s;
bool  instack[kMaxn];
int  nx,ny,maxmatch,first[kMaxn],next[kMaxm];Edge e[kMaxm];
int  cx[kMaxn],cy[kMaxn],distx[kMaxn],disty[kMaxn];
int  head,tail,q[kMaxn];

void  Input()
{
    cnt
= 0 ;
    memset(first2,
- 1 , sizeof (first2));
    
    scanf(
" %d%d " , & N, & M);
    
for ( int  i = 1 ;i <= M;i ++ )
    {
        
int  u,v;
        scanf(
" %d%d " , & u, & v);
        cnt
++ ;
        e2[cnt]
= v;
        next2[cnt]
= first2[u];
        first2[u]
= cnt;
    }
}

void  dfs( int  u)
{
    dfsn[u]
= low[u] =++ dfscnt;
    s.push(u);
    instack[u]
= true ;
    
for ( int  i = first2[u];i !=- 1 ;i = next2[i])
    {
        
int  v(e2[i]);
        
if ( ! dfsn[v])
        {
            dfs(v);
            low[u]
= min(low[u],low[v]);
        }
        
else   if (instack[v])
            low[u]
= min(low[u],dfsn[v]);
    }
    
if (dfsn[u] == low[u])
    {
        n
++ ;
        
int  v;
        
do
        {
            v
= s.top();s.pop();
            instack[v]
= false ;
            id[v]
= n;
        }
while (v != u);
    }
}

void  Tarjan()
{
    n
= dfscnt = 0 ;
    memset(dfsn,
0 , sizeof (dfsn));
    memset(instack,
false , sizeof (instack));
    
for ( int  i = 1 ;i <= N;i ++ )
        
if ( ! dfsn[i])
            dfs(i);
}

void  Rebuild()
{
    cnt
= 0 ;
    nx
= ny = n;
    memset(first,
- 1 , sizeof (first));
    
for ( int  u = 1 ;u <= N;u ++ )
        
for ( int  i = first2[u];i !=- 1 ;i = next2[i])
        {
            
int  v(id[e2[i]]);
            
if (id[u] == v)
                
continue ;
            
bool  found( false );
            
for ( int  j = first[id[u]];j !=- 1 ;j = next[j])
                
if (e[j].v == v)
                {
                    found
= true ;
                    
break ;
                }
            
if (found)
                
continue ;
            cnt
++ ;
            e[cnt].u
= id[u];e[cnt].v = v;
            next[cnt]
= first[id[u]];
            first[id[u]]
= cnt;
        }
}

bool  BFS()
{
    
bool  re( false );
    head
= tail = 0 ;
    memset(distx,
0 , sizeof (distx));
    memset(disty,
0 , sizeof (disty));
    
for ( int  i = 1 ;i <= nx;i ++ )
        
if (cx[i] ==- 1 )
            q[tail
++ ] = i;
    
while (head != tail)
    {
        
int  h,t;
        
for (h = head,t = tail;h != t;h = (h + 1 ) % kMaxn)
        {
            
int  u(q[h]);
            
for ( int  i = first[u];i !=- 1 ;i = next[i])
            {
                
int  v(e[i].v);
                
if ( ! disty[v])
                {
                    disty[v]
= distx[u] + 1 ;
                    
if (cy[v] ==- 1 )
                        re
= true ;
                    
else
                    {
                        distx[cy[v]]
= disty[v] + 1 ;
                        q[tail]
= cy[v];
                        tail
= (tail + 1 ) % kMaxn;
                    }
                }
            }
        }
        head
= t;
    }
    
return  re;
}

bool  DFS( int  u)
{
    
for ( int  i = first[u];i !=- 1 ;i = next[i])
    {
        
int  v(e[i].v);
        
if (disty[v] == distx[u] + 1 )
        {
            disty[v]
= 0 ;
            
if (cy[v] ==- 1   ||  DFS(cy[v]))
            {
                cx[u]
= v;
                cy[v]
= u;
                
return   true ;
            }
        }
    }
    
return   false ;
}

void  HopcroftKarp()
{
    maxmatch
= 0 ;
    memset(cx,
- 1 , sizeof (cx));
    memset(cy,
- 1 , sizeof (cy));
    
    
while (BFS())
    {
        
for ( int  i = 1 ;i <= nx;i ++ )
            
if (cx[i] ==- 1   &&  DFS(i))
                maxmatch
++ ;
    }
}

void  Output()
{
    printf(
" %d\n " ,n - maxmatch);
}

int  main()
{
    
int  T;
    scanf(
" %d " , & T);
    
while (T -- )
    {
        Input();
        Tarjan();
        Rebuild();
        HopcroftKarp();
        Output();
    }
    
    
return   0 ;
}

你可能感兴趣的:(HDU 3861 The King’s Problem)