Codeforces1027D-Mouse Hunt

Codeforces1027D-Mouse Hunt_第1张图片
题解:
还是比较水的一道题
先找强连通分量缩点,然后把所有出度为0的强连通分量内 c[i] c [ i ] 的最小值相加就是答案
注意自环!
Code C o d e :

#include
#include
#include
#define N 200005
using namespace std;
int tot,head[N],n,c[N],a[N],low[N],dfn[N],mn[N],Q[N];
int flag[N],deep,color[N],top,sum,Head[N],Tot,out[N];
struct node
{
    int vet,next;
}edge[N],Edge[N];
void add(int u,int v)
{
    edge[++tot]=(node){v,head[u]};
    head[u]=tot;
}
void Add(int u,int v)
{
    Edge[++Tot]=(node){v,Head[u]};
    Head[u]=Tot;
}
void tarjan(int u)
{
    low[u]=dfn[u]=++deep;
    Q[++top]=u;flag[u]=true;
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].vet;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(flag[v])
            low[u]=min(low[u],low[v]);
    }
    if(low[u]==dfn[u])
    {
        color[u]=++sum;
        flag[u]=0;
        while(Q[top]!=u)
        {
            flag[Q[top]]=false;
            color[Q[top--]]=sum;
        }
        top--;
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]!=i)add(i,a[i]);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
    memset(mn,0x3f3f3f,sizeof(mn));
    for(int i=1;i<=n;i++)
    {
        mn[color[i]]=min(mn[color[i]],c[i]);
        if(color[i]!=color[a[i]]&&i!=a[i])
        {
            Add(color[i],color[a[i]]);
            out[color[i]]++;
        }
    }
    int ans=0;
    for(int i=1;i<=sum;i++)
        if(!out[i])ans+=mn[i];
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(=====图论=====,#,强连通分量,Codeforces)