元の質問ポータル
まず第一に、あなたは、リングを見つけるのエンドポイントを列挙し、楽しみにして、前方唯一の方法があることは、この保証するからしなければならない。
リングを見つけた後、コストの計算方法参照してください。
リングの合計を想定された和の合計s u m、リングの要素数len lenl e n、リングMの最小要素、最小値M i n、入力全体の最小要素minw minwm i n w
- len = 1 len = 1 l e n=1.リング全体は自分自身を指し示す1つの要素にすぎず、何も必要ありません
- len-2 len-2 l e n−2. 2つの要素が互いにポイントし、それを交換するだけで、コストは合計になりますS U M
- len> 2 len> 2 l e n>2.ドラフトペーパーでそれをシミュレートすると、各要素がそのターゲット位置に一度交換され、途中に別のlen − 1 len-1を助けるトランジットとしての要素があることが理解できます。l e n−1つの要素を交換すると同時に、自分自身を交換します。要素は自然に最小、つまり最小のMM i n、その次数、合計len − 1 len-1l e n−一度、すべての要素が一度交換されると、より多くのlen − 2 len-2が交換されることも理解できます。l e n−2回。したがって、コストはsum +(len − 2)M in sum +(len-2)MinS U M+(l e n−2 )M i n
しかし、別の解決策があります。リングの外の要素をトランジットとして取ることができるため、部外者は最小入力、つまりminw minwを満たす必要があります。m i n w、次にコストを計算します。ここでは繰り返しません。合計+最小+(len + 1)minw sum + Min +(len + 1)minwS U M+M I N+(l e n+1 )m i n w
コード:
#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
LL w[maxn], ans, sum, len, Min, minw;
int a[maxn], b[maxn], pre[maxn], vis[maxn], n;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void dfs(int u){
vis[u] = 1, sum += w[a[u]], ++len, Min = min(Min, w[a[u]]);
if (!vis[pre[b[u]]]) dfs(pre[b[u]]);
}
int main(){
n = read();
minw = 1e9;
for (int i = 1; i <= n; ++i) minw = min(minw, w[i] = read());
for (int i = 1; i <= n; ++i) pre[a[i] = read()] = i;
for (int i = 1; i <= n; ++i) b[i] = read();
for (int i = 1; i <= n; ++i)
if (!vis[i]){
sum = 0, len = 0, Min = 1e9;
dfs(i);
if (len == 1);
else if (len == 2) ans += sum;
else ans += sum + min((len - 2) * Min, (len + 1) * minw + Min);
}
printf("%lld\n", ans);
return 0;
}