zoukankan      html  css  js  c++  java
  • POJ2942 Knights of the Round Table

    原题链接

    建补图,这样题目要求的即是求有多少个点没有被任何奇环包含。
    这里有两个结论:

    1. 若两个骑士属于两个不同的(v-DCC),那么这两个骑士肯定不能一起出席会议。
    2. 若在某个(v-DCC)中,存在一个奇环,那么该点双连通分量中所有点都被至少一个奇环包含。

    所以,我们只需要在用(tarjan)(v-DCC)的过程中,判断每个(v-DCC)是否包含奇环,若包含奇环,那么该(v-DCC)里所有骑士都可以出席会议。
    判断奇环可以使用染色法,因为一个奇环中必定有一对相邻点的颜色相同。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1010;
    const int M = 1e6 + 10;
    int a[N][N], fi[N], di[M << 1], ne[M << 1], st[N], dfn[N], low[N], co[N], v[N], DCC[N], l, tp, ti, d, v_DCC;
    bool jo[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 int minn(int x, int y)
    {
    	return x < y ? x : y;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    bool dfs(int x, int c)
    {
    	int i, y;
    	bool p = false;
    	co[x] = c;
    	for (i = fi[x]; i; i = ne[i])
    	{
    		y = di[i];
    		if (!(v[y] ^ v_DCC))
    		{
    			if (!co[y])
    				p = dfs(y, c ^ 1);
    			else
    				if (!(co[y] ^ c))
    					return true;
    		}
    	}
    	return p;
    }
    void tarjan(int x)
    {
    	int i, j, y, z;
    	dfn[x] = low[x] = ++ti;
    	st[++tp] = x;
    	for (i = fi[x]; i; i = ne[i])
    	{
    		y = di[i];
    		if (!dfn[y])
    		{
    			tarjan(y);
    			low[x] = minn(low[x], low[y]);
    			if (low[y] >= dfn[x])
    			{
    				++v_DCC;
    				d = 0;
    				do
    				{
    					z = st[tp--];
    					v[z] = v_DCC;
    					DCC[++d] = z;
    					co[z] = 0;
    				} while (z ^ y);
    				v[x] = v_DCC;
    				co[x] = 0;
    				DCC[++d] = x;
    				if (dfs(x, 2))
    					for (j = 1; j <= d; j++)
    						jo[DCC[j]] = 1;
    			}
    		}
    		else
    			low[x] = minn(low[x], dfn[y]);
    	}
    }
    int main()
    {
    	int i, n, m, j, x, y, s;
    	while (1)
    	{
    		s = n = re();
    		m = re();
    		if (!n && !m)
    			return 0;
    		memset(a, 0, sizeof(a));
    		memset(fi, 0, sizeof(fi));
    		memset(dfn, 0, sizeof(dfn));
    		memset(low, 0, sizeof(low));
    		memset(v, 0, sizeof(v));
    		memset(jo, 0, sizeof(jo));
    		l = ti = v_DCC = tp = 0;
    		for (i = 1; i <= m; i++)
    		{
    			x = re();
    			y = re();
    			a[x][y] = a[y][x] = 1;
    		}
    		for (i = 1; i < n; i++)
    			for (j = i + 1; j <= n; j++)
    				if (!a[i][j])
    				{
    					add(i, j);
    					add(j, i);
    				}
    		for (i = 1; i <= n; i++)
    			if (!dfn[i])
    			{
    				if (!fi[i])
    					continue;
    				tarjan(i);
    			}
    		for (i = 1; i <= n; i++)
    			if (jo[i])
    				s--;
    		printf("%d
    ", s);
    	}
    	return 0;
    }
    
  • 相关阅读:
    node项目发布pm2
    图片地址获取图片信息
    前端文件上传 获取文件大小 获取图片宽高
    前端上传图片预览
    vue按钮防暴力点击
    小程序父子组件之间的通信
    form表单
    es6-函数的扩展
    php的魔术常量以及类的模式方法
    OpenStack笔记
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9627249.html
Copyright © 2011-2022 走看看