第十二章 贪心 3 AcWing 1553. 用 Swap(0, i) 操作进行排序
原题链接
AcWing 1553. 用 Swap(0, i) 操作进行排序
算法标签
贪心 置换群
思路
构图
如何增加有向边
节点编号为i的节点对应位置为p[i],增加有向边i——>p[i]
节点编号为0的节点对应位置为1,增加有向边0——>1, 节点编号为1的节点对应位置为3,增加有向边1——>3, 节点编号为3的节点对应位置为4,增加有向边3——>4,节点编号为4的节点对应位置为0,增加有向边4——>0。
点编号为2的节点对应位置为2,增加有向边2——>2 构成自环
最终目标
将n个节点构成自环(节点编号为i的节点对应位置为p[i])
进行swap操作对环的影响
以节点0为起点,先对节点0所在的环进行操作, 将节点0与环内next点进行swap操作,节点0所在的环操作完毕, 与环外点swap使两环合并为一环, 继续上述操作, 详细思路见代码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define xx first
#define yy second
#define ump unordered_map
#define us unordered_set
#define pq priority_queue
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>=b;--i)
using namespace std;
typedef pair<int, int> PII;
const int N=100005, inf=0x3f3f3f3f3f3f3f3f, mod=1e9+7;
const double Exp=1e-8;
//int t, n, m, cnt, ans;
int p[N];
inline int rd(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put(int x) {
if(x<0) putchar('-'),x=-x;
if(x>=10) put(x/10);
putchar(x%10^48);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n=rd();
rep(i, 0, n){
int id=rd();
p[id]=i;
}
int res=0;
for(int i=1; i<n;){
// 节点0所在的环操作完毕 p[0]=0
while(p[0]){
swap(p[0], p[p[0]]);
++res;
}
// 点0所在的环找到非自环节点i
while(i<n&&p[i]==i){
++i;
}
if(i<n){
swap(p[0], p[i]);
++res;
}
}
printf("%lld", res);
return 0;
}
参考文献
AcWing 1553. 用 Swap(0, i) 操作进行排序(PAT甲级辅导课)y总视频讲解
原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈