在这里我要说一句,
我爱并查集一辈子
因为今晚的图论神仙场,差点被虐哭
第一题不知道为什么老是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&°[e[i].b]==2)//有两条边!!is OK!!!
unionset(e[i].a,e[i].b);
}
cout<<ans;
return 0;
}