zoukankan      html  css  js  c++  java
  • Codeforces--Books Exchange (hard version)

    题目链接http://codeforces.com/contest/1249/problem/B2 。并查集思想,将数分成多个集合,每个集合的大小就是一轮的所需天数。

    Map[i]存储数据。

    flag[i]来表示第i个数是否被访问过。

    mm[i]记录第i个集合所对应的集合大小,索引i为第i个集合的根对应的值。

    getParent方法利用递归的思想更新每个节点的上继,直接指向当前集合的根。

    由于访问过的集合不再进行访问,因此,分析时间复杂度,准确是O(CN),C为一个常数。在这里需要注意的是,mm在每次使用后要清,不然会有问题。

     1 #include<bits/stdc++.h>
     2 
     3 /*
     4 * 并查集
     5 */
     6 
     7 using namespace std;
     8 
     9 static const int MAX = 200005;
    10 
    11 int Map[MAX];
    12 bool flag[MAX];
    13 map<int, int> mm;
    14 
    15 int getParent(int x){
    16     if(!flag[x]){
    17         flag[x] = true;
    18         Map[x] = getParent(Map[x]);
    19     }
    20     return Map[x];
    21 }
    22 
    23 int main(){
    24     int q;
    25     scanf("%d", &q);
    26     while(q--){
    27         int n;
    28         scanf("%d", &n);
    29         for(int i=1;i<=n;i++){
    30             flag[i] = false;
    31         }
    32 
    33         // construct set
    34         int tmp;
    35         for(int i=1;i<=n;i++){
    36             scanf("%d", &Map[i]);
    37         }
    38 
    39         // solve
    40         for(int i=1;i<=n;i++){
    41             int parent = getParent(i);
    42             mm[parent]++;
    43         }   
    44 
    45         for(int i=1;i<=n;i++){
    46             if(i==1){
    47                 printf("%d", mm[Map[i]]);
    48             }
    49             else{
    50                 printf(" %d", mm[Map[i]]);
    51             }
    52         }
    53         printf("
    ");
    54         mm.clear();
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    求最小公倍数,最大公约数
    C> gcc函数属性__nothrow__, __leaf__
    Linux进程通信
    Linux 系统编程学习笔记
    Linux 系统编程学习笔记
    Linux 系统编程学习笔记
    Linux 系统编程学习笔记
    Linux 系统编程学习笔记
    Linux 系统编程学习笔记
    Linux> gcc编译选项
  • 原文地址:https://www.cnblogs.com/sgatbl/p/11746984.html
Copyright © 2011-2022 走看看