HDU 1827 Summer Holiday 强连通缩点

来源:互联网 发布:制作livephoto的软件 编辑:程序博客网 时间:2024/05/29 10:05

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=1827

思路

强连通缩点,找入度为0的点的个数。花费最少要计算出缩点的权值,其值为缩点内权值最小的点的权值。

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 1e3+10;int w[maxn];vector<int> g[maxn];int dfn[maxn],low[maxn],Stack[maxn],Belong[maxn],Min[maxn];int index,top,scc;bool Instack[maxn],In[maxn];void tarjan(int u){    dfn[u]=low[u]=++index;    Instack[u]=1;    Stack[top++]=u;    for(int i=0,L=g[u].size();i<L;i++)    {        int v=g[u][i];        if(!dfn[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else if(Instack[v])            low[u]=min(low[u],low[v]);    }    if(dfn[u]==low[u])    {        scc++;        int x;        do        {            x=Stack[--top];            Instack[x]=0;            Belong[x]=scc;        }while(x!=u);    }}void solve(int n){    memset(dfn,0,sizeof(dfn));    memset(In,0,sizeof(In));    scc=index=top=0;    for(int i=1;i<=n;i++)    Min[i]=INF;    for(int i=1;i<=n;i++)    if(!dfn[i])tarjan(i);    for(int i=1;i<=n;i++)    Min[Belong[i]]=min(Min[Belong[i]],w[i]);    for(int u=1;u<=n;u++)    for(int j=0,L=g[u].size();j<L;j++)    {        int v=g[u][j];        if(Belong[u]!=Belong[v])        {            In[Belong[v]]=1;        }    }    int num=0,cost=0;    for(int i=1;i<=scc;i++)    if(In[i]==0)    num++,cost+=Min[i];    printf("%d %d\n",num,cost);//  printf("scc:%d\n",scc);}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int u,v;        for(int i=0;i<=n;i++)g[i].clear();        for(int i=1;i<=n;i++)        scanf("%d",&w[i]);        for(int i=0;i<m;i++)        {            scanf("%d%d",&u,&v);            g[u].push_back(v);        }        solve(n);    }}