题的地址:http://codeforces.com/contest/977/problem/E
这个是简单深搜,但是自己写的太烂了,我用并查集就是为了一个连通分图只遍历一次,但可以边深搜边标记,这样就省掉了并查集的时间,我写的时间是一千多秒,但后面那样写就几百秒,真的是强
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N = 200005;
vector<int>ve[N];
int b[N];
int n,m;
int find2(int x)
{
int i = x;
while(x != b[x])
{
x = b[x];
}
int p;
while(i != b[i])
{
p = i;
i = b[i];
b[p] = x;
}
return x;
}
void find1(int x,int y)
{
int p = find2(x);
int q = find2(y);
if(p != q){
b[p] = b[q];
}
}
bool vis[N];
bool flag[N];
int ans;
bool dfs(int x,int num)
{
if(ve[x].size() > 2){
return false;
}
// cout << x << endl;
for(int i = 0;i < ve[x].size();++i)
{
if(ve[x][i] == ans && num > 1){
return true;
}
if(!flag[ve[x][i]]){
flag[ve[x][i]] = true;
return dfs(ve[x][i],num + 1);
}
}
return false;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
for(int i = 1;i <= n;++i)
b[i] = i;
for(int i = 0;i < m;++i)
{
int p,q;
scanf("%d %d",&p,&q);
ve[p].push_back(q);
ve[q].push_back(p);
find1(p,q);
}
// for(int i = 1;i <= n;++i)
// {
// for(int j = 0;j < ve[i].size();++j)
// {
// printf("%d ",ve[i][j]);
// }
// printf("\n");
// }
memset(vis,false,sizeof(vis));
int num = 0;
for(int i = 1;i <= n;++i)
{
if(!vis[find2(i)]){
ans = i;
memset(flag,false,sizeof(flag));
flag[i] = true;
if(dfs(i,0)){
// printf("true\n");
num++;
}
vis[find2(i)] = true;
}
}
printf("%d\n",num);
for(int i = 1;i <= n;++i)
ve[i].clear();
}
return 0;
}
200多秒的代码:边深搜边标记
#include<bits/stdc++.h>
using namespace std;
vector<int>v[200001];
bool f[200001];
bool g;
void dfs(int x){
f[x]=1;
if (v[x].size()!=2)g=0;
for (int i:v[x])
if (!f[i])dfs(i);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int ans=0;
for (int i=1;i<=n;i++){
g=1;
if (!f[i]){
dfs(i);
if (g){ans++;}
}
}
cout<<ans<<endl;
}