这个题目跟同比赛的
Exploration类似,做法也类似。
在那道题目只需要判断出是否存在环。
而这道题目则判读这个环的边是奇数边还是偶数边。
我这边采用的方法是用num表示这个点在搜索到第几条边是被搜到。下次在被搜到的时候,边数减掉上一次搜到时候的边数,就是从这个点出发回到这个点的边数了。然后判断一下奇偶就可以了。假如已经有奇数和偶数,就不用在继续搜了,直接结束,也算是小小的剪枝。
#pragma comment(linker, "/STACK:102400000,102400000")
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define MAX 110000
bool tg[2];
int head[MAX];
bool vis[MAX << 1];
int num[MAX];
int cnt;
struct edge
{
int v;
int next;
}edg[MAX << 1];
void init()
{
cnt = 0;
memset(head, -1, sizeof head);
memset(num, -1, sizeof num);
memset(vis, 0, sizeof vis);
memset(tg, 0, sizeof tg);
}
void addedge(int u, int v)
{
edg[cnt].v = v;
edg[cnt].next = head[u];
head[u] = cnt++;
swap(u, v);
edg[cnt].v = v;
edg[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u,int cnt2)
{
if (tg[0] && tg[1])
return;
for (int i = head[u]; i != -1; i = edg[i].next)
{
int v = edg[i].v;
if (!vis[i])
{
vis[i] = 1;
vis[i ^ 1] = 1;
if (num[v]!=-1)
tg[(cnt2 + 1 - num[v]) & 1] = 1;
else
num[v] = cnt2 + 1;
dfs(v, cnt2 + 1);
}
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n, m;
scanf("%d%d", &n, &m);
int u, v;
init();
while (m--)
{
scanf("%d%d", &u, &v);
addedge(u, v);
}
for (int i = 1; i <= n; i++)
{
if (num[i]==-1)
{
num[i] = 0;
dfs(i, 0);
}
}
if (tg[1])
puts("YES");
else
puts("NO");
if (tg[0])
puts("YES");
else
puts("NO");
}
}