题目大意
有
n
n
n个房间,每个房间都有一条连出去的通道,连向另一个房间
a
i
a_i
ai。
初始时刻,老鼠会出现在
[
1
,
n
]
[1,n]
[1,n]中的任意一个房间里。
下一个时刻,老鼠将沿着这个房间连出去的通道,逃跑到另一个房间。
现在要在房间里布置陷阱来抓捕老鼠,在第
i
i
i个房间里布置一个陷阱需要花费
c
i
c_i
ci的代价。
假设陷阱很强,一定能抓到跑到该房间的老鼠。
问最少要花费多少代价,才能保证无论初始时刻老鼠出现在哪一个房间都能把老鼠抓获。
时间限制
2s
数据范围
n
≤
2
×
1
0
5
n\le 2\times10^5
n≤2×105
c
i
≤
1
0
4
c_i\le 10^4
ci≤104
题解
要想花更小的代价就抓到老鼠,显然需要在老鼠的必经之路上不设陷阱。
那哪些房间才是必经之路呢?
不妨简单观察一下老鼠在每个点出发之后的路径,不难发现,最后老鼠一定是在一个环(包括自环)中。
那么显然这个环就是必经之路了,只需要在这个环里找一个代价最小的房间布设陷阱即可。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#define ll long long
#define G getchar
using namespace std;
ll read()
{
char ch;
for(ch = G();ch < '0' || ch > '9';ch = G());
ll n = 0;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n;
}
void write(ll x)
{
if (x > 9)
{
write(x / 10);
putchar(x % 10 + 48);
}
else putchar(x + 48);
}
const int N = 200005;
int n , a[N] , col[N] , mi[N] , v[N] , cnt , ans;
int z[N] , top;
bool bz[N];
int dfs(int x)
{
if (!bz[x])
{
if (col[x] == 0)
{
cnt++;
col[x] = cnt;
}
return col[x];
}
bz[x] = 0;
col[x] = dfs(a[x]);
return col[x];
}
void work(int x)
{
top = 0;
for ( ; bz[x] ;)
{
bz[x] = 0;
top++;
z[top] = x;
x = a[x];
}
mi[col[x]] = v[x];
for ( ; z[top] != x ;)
{
mi[col[x]] = min(mi[col[x]] , v[z[top]]);
bz[z[top]] = 1;
top--;
}
for ( ; top ; )
{
bz[z[top]] = 1;
top--;
}
}
int main()
{
//freopen("i.in","r",stdin);
//freopen("e.out","w",stdout);
n = read();
for (int i = 1 ; i <= n ; i++)
v[i] = read();
for (int i = 1 ; i <= n ; i++)
a[i] = read();
memset(bz , 1 , sizeof(bz));
cnt = 0;
for (int i = 1 ; i <= n ; i++)
if (bz[i]) col[i] = dfs(i);
memset(mi , 127 , sizeof(mi));
memset(bz , 1 , sizeof(bz));
for (int i = 1; i <= n ; i++)
if (mi[col[i]] > 10000) work(i);
ans = 0;
for (int i = 1 ; i <= cnt ;i++)
ans = ans + mi[i];
printf("%d\n", ans);
return 0;
}