HDU 1827(强连通+缩点 判入度)

请教了月光大牛和DK大牛 具体思路是首先提取强连通分量 然后将分量缩点重新构图 记录各点入度 将入度为0的点所代表的分量中的费用最小值记录下来 相加得到最小费用 其入度为0点的个数就是要求的通知的人数

 

具体代码如下 使用Tarjan寻找强连通 顺便ORZ两位大牛

 

 

#include  < iostream >
#include 
< stack >
#include 
< queue >
using   namespace  std;
typedef 
struct   
{
    
long  v,next;
}Edge;

typedef 
struct
{
    
long  Num;
    
long  Used;
    
long  Alive;
    
long  Low;
    
long  belong;
    
void  init( long  pos)
    {
        Num
= Used = Alive = Low = 0 ;
        belong
= pos;
    }
}Node;

const   long  MAXN = 2100 ;
long  N,M; // 点,边
Edge e[MAXN]; // 边数组
long  p[MAXN >> 1 ]; // 辅助数组
long  In[MAXN >> 1 ];
Node vec[MAXN
>> 1 ]; //
stack < long >  s;
long  Permit; // 时间戳

typedef 
struct
{
    
long  id;
    
long  cost;
}Man;

priority_queue
< Man >  q;
bool  hash[MAXN >> 1 ];

inline 
bool   operator   < ( const  Man a, const  Man b)
{
    
return  a.cost > b.cost;
}

inline 
void  init()
{
    
long  i;

    
while  ( ! s.empty())
    {
        s.pop();
    }

    
while  ( ! q.empty())
    {
        q.pop();
    }

    Permit
= 0 ;
    memset(hash,
0 , sizeof (hash));
    memset(p,
- 1 , sizeof (p));
    memset(In,
0 , sizeof (In));

    
for  (i = 0 ;i <= N; ++ i)
    {
        vec[i].init(i);
    }

    
for  (i = 1 ;i <= N; ++ i)
    {
        Man tt;
        scanf(
" %ld " , & tt.cost);
        tt.id
= i;
        q.push(tt);
    }

    
for  (i = 0 ;i < M; ++ i)
    {
        
long  from,to;
        scanf(
" %ld %ld " , & from, & to);
        e[i].next
= p[from];
        e[i].v
= to;
        p[from]
= i;
    }

}

inline 
void  update( long   & a, long  b)
{
    
if (a > b) a = b;
}


inline 
void  dfs( long  pos)
{
    s.push(pos);
    vec[pos].Low
= vec[pos].Num =++ Permit;
    vec[pos].Used
= vec[pos].Alive = true ;

    
long  j;
    
for  (j = p[pos];j !=- 1 ;j = e[j].next)
    {
        
long  to = e[j].v;
        
if  (vec[to].Used)
        {
            
if  (vec[to].Alive)
            {
                update(vec[pos].Low,vec[to].Num);
            }
        }
        
else
        {
            dfs(to);
            update(vec[pos].Low,vec[to].Low);
        }
    }

    
if  (vec[pos].Num == vec[pos].Low)
    {
        
long  t;
        
while  ((t = s.top()) != pos)
        {
            vec[t].belong
= pos;
            vec[t].Alive
= false ;
            s.pop();
        }
        vec[pos].belong
= pos;
        vec[pos].Alive
= false ;
        s.pop();
    }

}

inline 
void  Tarjan()
{
    
long  i;
    
for  (i = 1 ;i <= N; ++ i)
    {
        
if  ( ! vec[i].Used)
        {
            dfs(i);
        }
    }
}



int  main()
{
    
    
while  (scanf( " %ld %ld " , & N, & M) != EOF)
    {
        init();   
        Tarjan();        
        
long  i,j;
        
for  (i = 1 ;i <= N; ++ i)
        {
            
for  (j = p[i];j !=- 1 ;j = e[j].next)
            {
                
long  from = vec[i].belong;
                
long  to = vec[e[j].v].belong;
                
if (from != to)
                {
                    
++ In[to];
                }
            }    
        }
        
long  cost = 0 ,ct = 0 ;
        
while  ( ! q.empty())
        {
            Man t
= q.top();
            q.pop();

            
long  father = vec[t.id].belong;

            
if  (In[father] != 0 || hash[father])
            {
                
continue ;
            }
            
else
            {
                
++ ct;
                cost
+= t.cost;
                hash[father]
= true ;
                
++ In[father];
            }
        }    
        printf(
" %ld %ld\n " ,ct,cost);
        
    }
    
return   0 ;
}

你可能感兴趣的:(HDU)