现在的位置: 首页 > 综合 > 正文

hdu 1827 (强连通基础题)

2019年04月10日 ⁄ 综合 ⁄ 共 1170字 ⁄ 字号 评论关闭

// Tarjan+缩点:找出入度为0的强连通分量,

//找出每个强连通分量的最小费用求和


#include<stdio.h>
#include<stack>
using namespace std;
#define N 1002
int n,m,dfs[N],low[N],ins[N];
int in[N],belong[N],ct[N],cnt[N];
struct edge
{
    int ed;
    struct edge *next;
}*p[2*N];
void add(int x,int y)
{
    edge *q=new edge;
    q->ed=y;
    q->next=p[x];
    p[x]=q;
}
int ans,idx;
stack<int>Q;
void Tarjan(int x)
{
     
  int v;
  dfs[x]=low[x]=idx++;
  Q.push(x);
  ins[x]=1;
  for( edge *j=p[x];j;j=j->next)
  {
      if(dfs[j->ed]==-1)
      {
          Tarjan(j->ed);
          low[x]=low[x]>low[j->ed]?low[j->ed]:low[x];
      }
      else if(ins[j->ed]==1)//如果ed已经进栈
          low[x]=low[x]>dfs[j->ed]?dfs[j->ed]:low[x];
  }   
  if(low[x]==dfs[x])
  {
      ans++;
      while(1)
      {
         
          v=Q.top();
          Q.pop();
          ins[v]=0;
          belong[v]=ans;//缩点,一个强连通分量缩为一个点ans
          if(v==x)break;
      }
     
  }
}
int main()
{
    int i,x,y;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=0;i<=n;i++)
        {
            p[i]=NULL;
            dfs[i]=-1;
            ins[i]=0;
            in[i]=0;
            ct[i]=111111111;
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d",&cnt[i]);
        }
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        ans=idx=0;
        for(i=1;i<=n;i++)
            if(dfs[i]==-1)
                 Tarjan(i);
            for(i=1;i<=n;i++)
            {
                edge *q=p[i];
                while(q)
                {
                    if(belong[q->ed]!=belong[i])
                    {
                        in[belong[q->ed]]++;//入度
                    }
                    q=q->next;
                }
                if(ct[belong[i]]>cnt[i])ct[belong[i]]=cnt[i];//求每个缩后的点的最小费用
            } 
            int flag=0,k=0;
            for(i=1;i<=ans;i++)
            {
                if(in[i]==0)
                {flag+=ct[i];k++;}
            }
                printf("%d %d\n",k,flag);
    }
    return 0;
}

抱歉!评论已关闭.