下面两份代码都是求点双然后判奇环
第一份代码是求出点双的同时判奇环
第二份是大众写法,求出点双保存之后再判奇环
我觉得我的思路应该是没有问题的
但是为什么第一份代码一直过不了?
第一份:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define MAXN 1005
#define MAXM 2000005
#define reg register
#define inl inline
using namespace std;
int n, m;
int tot, hd[MAXN], nxt[MAXM], to[MAXM];
int tmp, dfn[MAXN], low[MAXN];
int cnt, res, in[MAXN], col[MAXN];
int top, st[MAXN];
bool ht[MAXN][MAXN], ans[MAXN];
inl void Clear()
{
tot = tmp = cnt = res = top = 0;
memset(hd, 0, sizeof hd);
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(col, 0, sizeof col);
memset(in, 0, sizeof in);
memset(ht, false, sizeof ht);
memset(ans, false, sizeof ans);
return;
}
inl void Link(int u, int v)
{
tot++;
nxt[tot] = hd[u];
to[tot] = v;
hd[u] = tot;
return;
}
inl bool Check(int u, int c, int d)
{
col[u] = c;
for(reg int i = hd[u]; i; i = nxt[i])
{
int v = to[i];
if(in[v] != d) continue;
if(col[v])
{
if(col[v] != (3 - c)) return true;
else return false;
}
if(Check(v, (3 - c), d)) return true;
}
return false;
}
inl void Work(int st)
{
if(Check(st, 1, cnt)) for(reg int i = 1; i <= n; i++) if(in[i] == cnt) ans[i] = true;
return;
}
inl void Tarjan(int u)
{
dfn[u] = low[u] = ++tmp;
st[++top] = u;
for(reg int i = hd[u]; i; i = nxt[i])
{
int v = to[i];
if(!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
if(dfn[u] <= low[v])
{
cnt++;
int k;
do
{
k = st[top--];
in[k] = cnt;
} while(k != v);
in[u] = cnt;
Work(u);
}
}
else low[u] = min(low[u], dfn[v]);
}
return;
}
int main()
{
//freopen("Input.in", "r", stdin);
//freopen("Output.out", "w", stdout);
while(cin >> n >> m)
{
if(n == 0 && m == 0) return 0;
Clear();
for(reg int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
ht[u][v] = ht[v][u] = true;
}
for(reg int i = 1; i < n; i++)
{
for(reg int j = i + 1; j <= n; j++)
{
if(!ht[i][j] && !ht[j][i]) Link(i, j), Link(j, i);
}
}
for(reg int i = 1; i <= n; i++) if(!dfn[i]) Tarjan(i);
for(reg int i = 1; i <= n; i++) if(!ans[i]) res++;
printf("%d\n", res);
}
return 0;
}
AC代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#define MAXN 1005
#define MAXM 2000005
#define reg register
#define inl inline
using namespace std;
int n, m;
int tot, hd[MAXN], nxt[MAXM], to[MAXM];
int tmp, rt, dfn[MAXN], low[MAXN];
int cnt, res, in[MAXN], col[MAXN];
int top, st[MAXN];
bool ht[MAXN][MAXN], cv[MAXN], ans[MAXN];
vector<int> vd[MAXN];
inl void Clear()
{
tot = tmp = res = top = 0;
memset(hd, 0, sizeof hd);
memset(nxt, 0, sizeof nxt);
memset(to, 0, sizeof to);
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(in, 0, sizeof in);
memset(col, 0, sizeof col);
memset(ht, false, sizeof ht);
memset(cv, false, sizeof cv);
memset(ans, false, sizeof ans);
for(reg int i = 1; i <= cnt; i++) vd[i].clear();
cnt = 0;
return;
}
inl void Link(int u, int v)
{
tot++;
nxt[tot] = hd[u];
to[tot] = v;
hd[u] = tot;
return;
}
inl bool Check(int u, int c, int d)
{
col[u] = c;
for(reg int i = hd[u]; i; i = nxt[i])
{
int v = to[i];
if(in[v] != d) continue;
if(!col[v] && Check(v, (3 - c), d)) return true;
if(col[v] == c) return true;
}
return false;
}
inl void Tarjan(int u)
{
dfn[u] = low[u] = ++tmp;
st[++top] = u;
int c = 0;
for(reg int i = hd[u]; i; i = nxt[i])
{
int v = to[i];
if(!dfn[v])
{
c++;
Tarjan(v);
low[u] = min(low[u], low[v]);
if(dfn[u] <= low[v])
{
if(u != rt || c > 1) cv[u] = true;
vd[++cnt].push_back(u);
int k;
do
{
k = st[top--];
vd[cnt].push_back(k);
in[k] = cnt;
} while(k != v);
}
}
else low[u] = min(low[u], dfn[v]);
}
return;
}
int main()
{
//freopen("Input.in", "r", stdin);
//freopen("Output.out", "w", stdout);
while(true)
{
scanf("%d%d", &n, &m);
if(n == 0 && m == 0) return 0;
for(reg int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
ht[u][v] = ht[v][u] = true;
}
for(reg int i = 1; i < n; i++)
{
for(reg int j = i + 1; j <= n; j++)
{
if(!ht[i][j] && !ht[j][i]) Link(i, j), Link(j, i);
}
}
for(reg int i = 1; i <= n; i++) if(!dfn[i]) rt = i, Tarjan(i);
for(reg int i = 1; i <= cnt; i++)
{
for(reg vector<int>::iterator it = vd[i].begin(); it != vd[i].end(); it++)
{
int u = *it;
if(cv[u]) in[u] = i;
col[u] = 0;
}
if(Check(*(vd[i].begin()), 1, i))
{
for(reg vector<int>::iterator it = vd[i].begin(); it != vd[i].end(); it++)
{
int u = *it;
ans[u] = true;
}
}
}
for(reg int i = 1; i <= n; i++) if(!ans[i]) res++;
printf("%d\n", res);
Clear();
}
return 0;
}