题意:
。。。
思路:
尝试把排列分解成若干个环。
然后就会发现如果在环中连了一条边,最终整个环就会被连上。
所以有以下结论
1)如果有大小为1的环,即置换后不变的点,把其他点全部连在这个点上。
2)剩下的环中,如果存在奇环,则无解。
3)剩下的环中,如果不存在长度为2的环,则无解。
4)拿出一个长度为2的环,其它的环拆开后连在这个环的两个端点上,可以构造出树。
typedef vector<int> vec;
bool vis[N];
vector<vec> vv;
int pm[N], n;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++ i) scanf("%d", pm + i);
int pos1 = -1, pos2 = -1, _odd = 0;
for (int i = 1; i <= n; ++ i) {
if ( vis[i] ) continue;
vector<int> v;
int j = i;
while ( !vis[j] ) {
v.push_back(j);
vis[j] = 1;
j = pm[j];
}
vv.push_back(v);
if ( v.size() == 1 ) pos1 = i;
if ( v.size() == 2 ) pos2 = vv.size() - 1;
if ( v.size() > 2 && ( v.size() & 1 ) ) _odd = 1;
}
if ( pos1 != -1 ) {
puts("YES");
for (int i = 1; i <= n; ++ i)
if ( i != pos1 )
printf("%d %d\n", i, pos1);
return 0;
}
if ( _odd || pos2 == -1 ) {
puts("NO");
return 0;
}
puts("YES");
printf("%d %d\n", vv[pos2][0], vv[pos2][1]);
int sz = vv.size();
for (int i = 0; i < sz; ++ i) {
if ( i == pos2 ) continue;
for ( int j = 0, k = 0; j < vv[i].size(); ++ j, k ^= 1 ) {
printf("%d %d\n", vv[i][j], vv[pos2][k]);
}
}
return 0;
}