Codeforces Round 981 (Div. 3) E. Sakurako, Kosuke, and the Permutation

简单来说就给一个排列,每一个元素要满足其中一个:

  • pi=i
  • p[pi]=i

 其实我也没想到并查集和图;贪心然后WA掉惹 

将每一个节点和他的pi相连,会得到诺干的单向图,然后每一块图只需修改\frac{[n-1]}{2}便可让其成为两两一对的双向图(满足第二条),如果n为奇数,会独立出一个节点,这个节点在其他节点交换完成后一定满足第一条:因为一个图里的值如果是[a,b]那么它里面的元素也是在排列的[a,b]个中,

待其他交换完,剩下的那个只能留着pi = i的这个坑里面


    import java.util.Map;
    import java.util.Scanner;
    import java.util.TreeMap;

    public class CFR981E {
        int[] father;
        static int n;
        public void init(){
            father = new int[n];
            for(int i = 0; i < n; i++){
                father[i] = i;
            }
        }

        public int find(int u){
            if(u == father[u]){
                return u;
            }else
                return father[u] = find(father[u]);

        }

        public void join(int u,int v){
            u = find(u);
            v = find(v);
            if(u == v)
                return;
            father[u] = v;
        }

        public static void main(String[] args) {
            CFR981E uf = new CFR981E();
            int t;
            Scanner sc = new Scanner(System.in);
            t = sc.nextInt();
            while(t-- > 0){
                n = sc.nextInt();
                uf.init();
                int[] nums = new int[n];
                for(int i = 0; i < n; i++){
                    nums[i] = sc.nextInt() - 1;
                }
                for(int i = 0; i < n; i++){
                    uf.join(nums[i],nums[nums[i]]);
                }
                Map<Integer, Integer> map = new TreeMap<>();
                for(int i = 0; i < n; i++){
                    int cur = uf.find(nums[i]);
                    map.put(cur, map.getOrDefault(cur, 0) + 1);
                }
                int ans = 0;
                for(Integer val : map.values()){
                    ans += (val-1) / 2;
                }
                System.out.println(ans);
            }
        }
    }

凭什么和C一样的难度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值