欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces1027D-Mouse Hunt

程序员文章站 2024-03-17 10:14:10
...

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

#include<cstdio>
#include<cstring>
#include<algorithm>
#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;
}