1. 程式人生 > >CF1027D Mouse Hunt題解

CF1027D Mouse Hunt題解

題目:

伯蘭州立大學的醫學部剛剛結束了招生活動。和以往一樣,約80%的申請人都是女生並且她們中的大多數人將在未來4年(真希望如此)住在大學宿舍裡。

宿舍樓裡有nn個房間和一隻老鼠!女孩們決定在一些房間裡設定捕鼠器來除掉這隻可怕的怪物。在ii號房間設定陷阱要花費c_ic
i
​ 伯蘭幣。房間編號從11到nn。

要知道老鼠不是一直原地不動的,它不停地跑來跑去。如果tt秒時它在ii號房間,那麼它將在t+1t+1秒時跑到a_ia
i
​ 號房間,但這期間不會跑到別的任何房間裡(i=a_ii=a
i
​ 表示老鼠沒有離開原來的房間)。時間從00秒開始,一旦老鼠竄到了有捕鼠器的房間裡,這隻老鼠就會被抓住。

如果女孩們知道老鼠一開始在哪裡不就很容易嗎?不幸的是,情況不是這樣,老鼠在第00秒時可能會在從11到nn的任何一個房間內。

那麼女孩們最少要花多少錢設定捕鼠器,才能保證老鼠無論從哪個房間開始流竄最終都會被抓到?

分析:

stack解決

a向a[x]連邊

程式碼:

#include<cstdio>
#include<stack>
using namespace std;
int a[200005];
int cnt=0;
int vis[200005],c[200005];
int flag;
int tag;
stack<int>s;
void dfs(int x)
{
    if(a[x]==0)
    {
        return ;
    }
    cnt++;
    if(cnt>vis[x]&&vis[x])
    {
        flag=1;
        tag=x;
        a[x]=0;
        vis[x]=0;
        return ;
    }
    s.push(x);
    vis[x]=cnt;
    dfs(a[x]);
    vis[x]=0;
    a[x]=0;
}
int main()
{
    int n;
    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]);
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        while(!s.empty())s.pop();
        flag=0;
        dfs(i);
        if(flag)
        {
            int ans=2147483647;
            if(!s.empty())
            {
                while(!s.empty()&&s.top()!=tag)
                {
                    ans=min(ans,c[s.top()]);
                    s.pop();
                }
                if(!s.empty())
                ans=min(ans,c[s.top()]);
                sum+=ans;
            }
        }
    }
    printf("%d\n",sum);
    return 0;
}