CF B. Cyclic Components 并查集啊哈哈哈哈哈hiahiahia

在这里我要说一句,

我爱并查集一辈子

因为今晚的图论神仙场,差点被虐哭
第一题不知道为什么老是WA,好不容易AC后,感觉剩下一个小时也写不来什么东西了
把BCD都看了一遍,总感觉都会写,但是又不知道从哪里下手,D题感觉是用那个多源最短路径来写,无奈不会写
再返回B一看,咦?????????????????????
这玩意
不就dfs or 并查集吗????????


并查集
一辈子
再说一遍
我爱
并查集
一辈子

好吧,反正还剩十分钟也写不了了,把这题题解写一下~

首先我们要知道,这题里面说的成环,是说一个比较孤独的环 ~不能乱七八糟连一大堆其他的不能成环的顶点
所以一个环里,每个顶点的度为2
(如果可以有乱七八糟的点,怎么办呢?我觉得那应该要用到dfs?回头仔细想一想)
这一题并查集就可以做

可以union的条件:
条件1:两点相连
条件2:两点的度均为2

这个时候就可以union
如果它们本来就共祖,那么说明成环了,直接ans++;
(在这个union函数里面,还可以再加上一个member数组,用来存放该环的周长,但这题不用考虑)

不愧是模板题~

上代码:

#include<bits/stdc++.h>
using namespace std;
//typedef long long ll;
const int N=2e5+10;
int ans,n,m;
int deg[N];
struct edge{
    int a,b;
}e[N];
int f[N];//father,ahhahahahhhahahaahah并查集!!!!!!

int find(int x){return f[x]==x?x:f[x]=find(f[x]);}//查
void unionset(int x,int y){//并
    int r1=find(x),r2=find(y);
        if(r1!=r2) f[r2]=r1;
        else ans++;
}

int main(){
    scanf("%d%d",&n,&m);

    for(int i=1;i<=m;i++) f[i]=i;//初始化

    for(int i=0;i<m;i++){
        scanf("%d%d",&e[i].a,&e[i].b);
        deg[e[i].a]++;
        deg[e[i].b]++;
    }//has its order!!!!!!!!!

    for(int i=0;i<m;i++){
        if(deg[e[i].a]==2&&deg[e[i].b]==2)//有两条边!!is OK!!!
            unionset(e[i].a,e[i].b);
    }
        cout<<ans;
        return 0;
}

猜你喜欢

转载自www.cnblogs.com/guaguastandup/p/10347168.html