【题解】LuoGu3482:[POI2009] SLO-Elephants

元の質問ポータル
まず第一に、あなたは、リングを見つけるのエンドポイントを列挙し、楽しみにして、前方唯一の方法があることは、この保証するからしなければならない。
リングを見つけた後、コストの計算方法参照してください。
リングの合計を想定された和の合計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 n2. 2つの要素が互いにポイントし、それを交換するだけで、コストは合計になりますS U M
  • len> 2 len> 2 l e n>2.ドラフトペーパーでそれをシミュレートすると、各要素がそのターゲット位置に一度交換され、途中に別のlen − 1 len-1を助けるトランジットとしての要素があることが理解できます。l e n1つの要素を交換すると同時に、自分自身を交換します。要素は自然に最小、つまり最小のMM i n、その次数、合計len − 1 len-1l e n一度、すべての要素が一度交換されると、より多くのlen − 2 len-2が交換されることも理解できます。l e n2回。したがって、コストはsum +(len − 2)M in sum +(len-2)MinS U M+l e n2 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;
}

おすすめ

転載: blog.csdn.net/ModestCoder_/article/details/108555269