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;
}
posted @ 2008-08-27 12:06  Hdu-Lost  阅读(447)  评论(0编辑  收藏  举报