#include <iostream>
#include <deque>
#include <string.h>
using namespace std;
#define SIZE 100010
#define MIN(a, b) ((a) < (b) ? (a) : (b))
typedef struct _edg
{
int b, e;
}ST_EDGDS;
typedef struct _node
{
int node;
int next;
}ST_NODE;
ST_NODE cities[3 * SIZE];
int front[SIZE], rear[SIZE], DFN[SIZE], LOW[SIZE], bin_color[SIZE], Dindex, Lenght, ret;
deque<ST_EDGDS> Qedgs, Qconneted;
bool used[SIZE];
/*以邻接表存储边*/
void add_edg(int ai, int bi)
{
/* a new beginning node */
if (0 == front[ai] && 0 == rear[ai])
{
front[ai] = rear[ai] = ++Lenght;
cities[Lenght].node = ai;
}
cities[rear[ai]].next = ++Lenght;
rear[ai] = Lenght;
cities[Lenght].node = bi;
}
/*判断是否有奇数圈*/
int chk_odd()
{
int size, ai, bi, w = 1;
ST_EDGDS st_edg;
// size = Qconneted.size() + 1;
deque<ST_EDGDS>::iterator begin, end;
end = Qconneted.end();
// if (0 == size % 2)
{
memset(bin_color, 0, sizeof(bin_color));
for (begin = Qconneted.begin() ; begin != end ; begin++)
{
st_edg = *begin;
ai = st_edg.b;
bi = st_edg.e;
if (0 == bin_color[ai] && 0 == bin_color[bi])
{
bin_color[ai] = w;
bin_color[bi] = 0 - bin_color[ai];
}
else if (0 == bin_color[ai] && 0 != bin_color[bi])
bin_color[ai] = 0 - bin_color[bi];
else if (0 != bin_color[ai] && 0 == bin_color[bi])
bin_color[bi] = 0 - bin_color[ai];
else if (bin_color[ai] == bin_color[bi])
goto cnt;
}
/*返回-1,说明这是个二分图,不存在奇数圈*/
return -1;
}
cnt:
int add = 0;
for (begin = Qconneted.begin() ; begin != end ; begin++)
{
st_edg = *begin;
ai = st_edg.b;
bi = st_edg.e;
if (0 == used[ai])
{
add++;
used[ai] = 1;
}
}
return add;
}
int head_idx;
ST_EDGDS st_edg;
void tarjan(int crt_nd, int p_nd)
{
int next_nd, next_idx;
DFN[crt_nd] = LOW[crt_nd] = ++Dindex;
head_idx = front[crt_nd];
next_idx = cities[head_idx].next;
for ( ; 0 != next_idx ; next_idx = cities[next_idx].next)
{
next_nd = cities[next_idx].node;
/* means next_nd unvisited or have lower DFN, whatever, it's a new edg */
if (next_nd != p_nd && DFN[next_nd] < DFN[crt_nd])
{
st_edg.b = crt_nd;
st_edg.e = next_nd;
Qedgs.push_front(st_edg);
/* if next_nd visited, and have lower DFN */
if (0 != DFN[next_nd])
LOW[crt_nd] = MIN(LOW[crt_nd], DFN[next_nd]);
else
{
tarjan(next_nd, crt_nd);
LOW[crt_nd] = MIN(LOW[crt_nd], LOW[next_nd]);
if (LOW[next_nd] >= DFN[crt_nd])
{
int cnt = 0;
do
{
st_edg = Qedgs.front();
Qedgs.pop_front();
Qconneted.push_back(st_edg);
cnt++;
}while (!((st_edg.b == crt_nd && st_edg.e == next_nd) || (st_edg.b == next_nd && st_edg.e == crt_nd)));
/* check odd */
if (1 == cnt)
{
Qconneted.clear();
continue;
}
int add;
add = chk_odd();
if (-1 == add)
{
Qconneted.clear();
continue;
}
ret += add;
Qconneted.clear();
}
}
}
}
}
void solve(int size)
{
int i;
memset(DFN, 0 , sizeof(DFN));
memset(LOW, 0, sizeof(LOW));
/* from 1 to N */
for (i=1 ; i<=size ; i++)
{
if (0 == DFN[i])
tarjan(i, -1);
}
}
int main(int argc, char *argv[])
{
int T, N, M, i, ai, bi;
cin >> T;
while (T--)
{
Lenght = ret = Dindex = 0;
memset(front, 0, sizeof(front));
memset(rear, 0, sizeof(rear));
memset(cities, 0, sizeof(cities));
memset(used, 0, sizeof(used));
Qedgs.clear();
Qconneted.clear();
cin >> N >> M;
for (i=0 ; i<M ; i++)
{
scanf("%d %d", &ai, &bi);
add_edg(ai, bi);
add_edg(bi, ai);
}
solve(N);
cout << ret << endl;
}
}
|