求助
查看原帖
求助
183562
_ReClouds_楼主2021/10/4 09:07

下面两份代码都是求点双然后判奇环

第一份代码是求出点双的同时判奇环

第二份是大众写法,求出点双保存之后再判奇环

我觉得我的思路应该是没有问题的

但是为什么第一份代码一直过不了?

第一份:

#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;
}

2021/10/4 09:07
加载中...