Too Heavy ARC111 -C 思维,模拟,置换
Too Heavy ARC111 -C 思维,模拟,置换
题意
\(N\)个人体重为\(a_i\),拥有行李\(c_i\),\(i\)号行李的重量为\(b_i\)
现需要通过最少的交换次数使他们交换到自己的行李。
每次可以选择\(i,j\)并且交换\(i\)号人的行李和\(j\)号人的行李。
当某人的行李大于等于他自己的体重时此人无法再进行交换
\[1\leq N \leq 200000\\
1\leq a_i,b_i \leq 10^9\\
\]
分析
把\(c_i\)看成一种置换,即看成若干个有向环,若存在\(C\)个环,则很容易构造出最少的交换次数即\(N-C\)
这样贪心策略就是让体重最大的进行转移,若仍然不满足则输出-1
代码
int vis[maxn],g[maxn],p[maxn];
int a[maxn],b[maxn];
vector<pii> ans;
int main(){
int n = rd();
for(int i = 1;i <= n;i++)
a[i] = rd();
for(int i = 1;i <= n;i++)
b[i] = rd();
for(int i = 1;i <= n;i++)
p[i] = rd(),g[p[i]] = i;
for(int i = 1;i <= n;i++){
if(i == p[i] || vis[i]) continue;
if(a[g[i]] <= b[i]) {
cout << -1 << '\n';
return 0;
}
vector<int> v;
v.pb(i);
for(int j = p[i];j != i;j = p[j]){
if(a[g[j]] <= b[j]) {
cout << -1 << '\n';
return 0;
}
v.pb(j);
vis[j] = 1;
}
int pos = 0;
for(int j = 0;j < v.size();j++)
if(a[v[j]] > a[v[pos]])
pos = j;
for(int j = pos + 1;j < v.size();j++)
ans.pb(make_pair(v[pos],v[j]));
for(int j = 0;j < pos;j++)
ans.pb(make_pair(v[j],v[pos]));
}
cout << ans.size() << '\n';
for(auto it:ans){
cout << it.fi << ' ' << it.se << '\n';
}
}