## Cycle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description

N vertexes and M edges, you can select a vertex as your starting point, then you need to walk in the graph along edges. However, you can't pass a edge more than once, even opposite direction is forbidden. At the end, you should come back to the starting point. Assume you has passed X edges, there are two questions:

Question 1: Can X be a odd number ?

Question 2: Can X be a even number ?

(note: you must walk, so X

Input

T, indicating the number of test cases.

Each test case begins with two integer N, M, indicating the number of vertexes and the number of edges. Following M lines, each line contains two integers Ui, Vi, indicating there are a edge between vertex Ui and vertex Vi.

1 ≤ N ≤ 100000

0 ≤ M ≤ 300000

1 ≤ Ui,Vi ≤ N

Ui will not equal to Vi

There is at most one edge between any pair of vertex.

Output

For each test, print two lines.

The first line contains "YES" or "NO" for question 1.

The second line contains "YES" or "NO" for question 2.

Sample Input

3 1 0 3 3 1 2 2 3 3 1 4 4 1 2 2 3 3 4 4 1

Sample Output

Hint

If you need a larger stack size,

``````#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 100010;
const int MAXM = 300010;
struct Edge
{
int to, next;
bool cut;
} edge[MAXM << 1];
int Low[MAXN], DFN[MAXN], Stack[MAXN];
int Index, top;
bool Instack[MAXN];

{
edge[tot].to = v;
edge[tot].cut = false;
}

void Tarjan(int u, int pre)
{
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for (int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if (v == pre)continue;
if (!DFN[v])
{
Tarjan(v, u);
if (Low[u] > Low[v])
Low[u] = Low[v];
if (Low[v] > DFN[u])
{
edge[i].cut = true;
edge[i ^ 1].cut = true;
}
}
else if (Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if (Low[u] == DFN[u])
{
do
{
v = Stack[--top];
Instack[v] = false;
} while (v != u);
}
}

void init()
{
tot = 0;
}

void solve(int n)
{
memset(DFN, 0, sizeof(DFN));
memset(Instack, false, sizeof(Instack));
Index = top = 0;
for (int i = 1; i <= n; i++)
if (!DFN[i])
Tarjan(i, i);
}

int num;
int vis[MAXN], dep[MAXN], cnt[MAXN];
bool odd, even;

void dfs(int u, int depth, int pre)
{
vis[u] = 1; //vis标记的是双连通分量的点
dep[u] = depth;
cnt[u] = 1; //cnt标记的是当前遍历到的点
for (int i = head[u]; i != -1; i = edge[i].next)
{
if (edge[i].cut) continue;
int v = edge[i].to;
if(v == pre) continue;
if (vis[v])
{
if (cnt[v])
{
int len = dep[u] - dep[v] + 1;
if (len % 2 == 1)
{
odd = true;
num++;   //奇环的个数
if (num > 1)
even = true;
}
else
even = true;
}
}
else
dfs(v, depth + 1, u);
}
cnt[u] = 0;
}

int main()
{
int t;
scanf("%d", &t);
while (t--)
{
init();
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
}
solve(n);

odd = even = false;
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; i++)
{
if (!vis[i])
{
num = 0;
dfs(i, 1, -1);
}
}

printf("%s\n", odd ? "YES" : "NO");
printf("%s\n", even ? "YES" : "NO");
}
return 0;
}``````