洛谷2783 有机化学之神偶尔会做作弊

原题链接

很水的一道题,先用(tarjan)找边双连通分量并缩点,因为缩点后必然是一棵树,所以直接(LCA)求距离即可。
另外因为有重边(说好的只有单键呢),所以需要判重,一开始我用的(HASH)判重,结果又被卡了。。。
(HASH)天理难容,每次用都被卡
最后一气之下(bitset)判重,总算是过了。

#include<cstdio>
#include<cmath>
#include<bitset>
using namespace std;
const int N = 1e4 + 10;
const int M = 1e5 + 10;
const int K = 15;
int fi[N], di[M], ne[M], cfi[N], cdi[M], cne[M], dfn[N], low[N], de[N], bl[N], f[N][K], l = 1, lc, ti, DCC, gn;
bool bg[M];
bitset<N>v[N];
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline void add(int x, int y)
{
	di[++l] = y;
	ne[l] = fi[x];
	fi[x] = l;
}
inline void add_c(int x, int y)
{
	cdi[++lc] = y;
	cne[lc] = cfi[x];
	cfi[x] = lc;
}
inline int minn(int x, int y)
{
	return x < y ? x : y;
}
inline void sw(int &x, int &y)
{
	int z = x;
	x = y;
	y = z;
}
void tarjan(int x, int la)
{
	int i, y;
	dfn[x] = low[x] = ++ti;
	for (i = fi[x]; i; i = ne[i])
		if (!dfn[y = di[i]])
		{
			tarjan(y, i);
			low[x] = minn(low[x], low[y]);
			if (low[y] > dfn[x])
				bg[i] = bg[i ^ 1] = 1;
		}
		else
			if (i ^ la ^ 1)
				low[x] = minn(low[x], dfn[y]);
}
void dfs(int x)
{
	int i, y;
	bl[x] = DCC;
	for (i = fi[x]; i; i = ne[i])
		if (!bg[i] && !bl[y = di[i]])
			dfs(y);
}
void dfs_2(int x)
{
	int i, y;
	for (i = 1; i <= gn; i++)
		f[x][i] = f[f[x][i - 1]][i - 1];
	for (i = cfi[x]; i; i = cne[i])
		if ((y = cdi[i]) ^ f[x][0])
		{
			f[y][0] = x;
			de[y] = de[x] + 1;
			dfs_2(y);
		}
}
int lca(int x, int y)
{
	int i;
	if (de[x] > de[y])
		sw(x, y);
	for (i = gn; ~i; i--)
		if (de[f[y][i]] >= de[x])
			y = f[y][i];
	if (!(x ^ y))
		return x;
	for (i = gn; ~i; i--)
		if (f[x][i] ^ f[y][i])
		{
			x = f[x][i];
			y = f[y][i];
		}
	return f[x][0];
}
void pr(int x)
{
	if (!x)
		return;
	pr(x >> 1);
	printf("%d", x & 1);
}
int main()
{
	int i, n, m, t, x, y;
	n = re();
	m = re();
	gn = log2(n);
	for (i = 1; i <= m; i++)
	{
		x = re();
		y = re();
		if (v[x][y] || v[y][x])
			continue;
		v[x][y] = v[y][x] = 1;
		add(x, y);
		add(y, x);
	}
	tarjan(1, 0);
	for (i = 1; i <= n; i++)
		if (!bl[i])
		{
			++DCC;
			dfs(i);
		}
	for (i = 2; i <= l; i += 2)
	{
		x = bl[di[i ^ 1]];
		y = bl[di[i]];
		if (x ^ y)
		{
			add_c(x, y);
			add_c(y, x);
		}
	}
	de[1] = 1;
	dfs_2(1);
	t = re();
	while (t--)
	{
		x = bl[re()];
		y = bl[re()];
		pr(de[x] + de[y] - (de[lca(x, y)] << 1) + 1);
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9820407.html