codeforces 576B Invariance of Tree (观察)

题意:
。。。
思路:
尝试把排列分解成若干个环。
然后就会发现如果在环中连了一条边,最终整个环就会被连上。
所以有以下结论
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值