CodeForces#479 Div.3 E. Cyclic Components 并查集

题目链接

题意: 就是给你很多个图,让你判断这些图中成环的有多少个。
成环的图有个要求就是这个环上每个点的度数刚刚好等于2(不多不少刚刚好),如果度数超过2 , 就不是有效答案。
PS: 这道题wa了我2次,,,一次TLE,找了半天才发现原来我并查集还没有压缩路径 == ,然后第二次是运行错误,最后才发现是数组开的不够大(QAQ妈的开了10w的数组居然还不够用,,,然后赶紧回去看了下题目的范围,,,,好吧要开20w。。。大哥我错了对不起!!!!!!)

#include<bits/stdc++.h>
#define ll long long
using namespace std;

 int pre[600005] ;

 int find(int x) // 网上copy的find函数模板,相对来说还是喜欢递推,,,递归的话感觉可能会超时(我随便说的QAQ)
{
    int r=x;
    while(pre[r]!=r)
    r=pre[r];//找到他的前导结点
  int i=x,j;
   while(i!=r)//路径压缩算法
    {
        j=pre[i];//记录x的前导结点
        pre[i]=r;//将i的前导结点设置为r根节点
        i=j;
    }

    return r;
}

 void init(int n){  // 初始化并查集, 每个人都是自己的老大
   for(int i = 0 ; i <= n ; i++)
     pre[i] = i ;
 }


int du[1000000] ; // 记录每个点的度数
int sum[1000000] ; // 标记数组,本来是要开vis的,不知道为什么就开成这样了。。。
int main(){
  int n , m ;
   cin >> n >> m ;
   int ans = 0 ;
   int x , y ;
   init(n) ;
   for(int i = 0 ; i < m ; i++){
      cin >> x >> y ;
       du[x]++ ; du[y]++ ;
      int r = find(x) ;
      int l = find(y) ;
      if(r == l ) continue ;
      pre[r]  = l ; 连接边,如果看不懂的话可以去查下并查集的union

   }
   for(int i = 1 ; i <= n ; i++) {
       if(du[i]!= 2  ) { sum[find(i)] = 1 ; } // 这一步的意思是如果你的度数超过了2,我就重你的点开始找头结点,然后做标记。

   }
/*  for(int i = 1 ; i <= n ; i++) {
      cout << du[i] <<" " ;
  }cout << endl ;
    for(int i = 1 ; i <= n ; i++) {
      cout <<sum[i] <<" " ;
  }cout << endl ;
    for(int i = 1 ; i <= n ; i++) {
      cout << pre[i] <<" " ;
  }cout << endl ;
  */
     for(int i = 1 ; i  <= n ; i++){
    if(pre[i] == i && sum[i] != 1) ans++ ; 
// 并查集找图有个特性,就是你一个图,它所有的节点都会指向头节点,pre【i】 == i 的意思就是说你又多少个头结点,也就是有多少个图,在这N多个图中有多少个没有被标记的图的数量,这个数量就是我们要输出的ans 
   }
   cout << ans <<endl ;
}
/*
5 6
1 2
2 3
2 4
3 4
4 5
5 3
自测样例
*/

猜你喜欢

转载自blog.csdn.net/qq_42894605/article/details/81628223