zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
    
  • 相关阅读:
    tree命令详解
    rm 命令详解
    rename命令详解
    pwd命令详解
    mv命令详解
    mkdir命令详情
    find命令详解
    dockerfile中配置时区
    docker导入导出
    docker上传私有仓库报错
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9820407.html
Copyright © 2011-2022 走看看