Loading

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';
	}
}
posted @ 2021-02-05 10:18  MQFLLY  阅读(102)  评论(0编辑  收藏  举报