zoukankan      html  css  js  c++  java
  • [poj] 2942 Knights of the Round Table

    原题

    这不是一道点双联通分量板子题。
    首先,为什么这不是一道边双联通分量呢?
    可能我们会认为,一个边双联通分量里的两个点之间一定存在两天不重复的路径,但事实上,这两条不重复的路径,只保证了边是不重复的,却没有保证点是不重复的。而在这道题里,显然,一个人不能坐在同一桌的两个位置。
    那么为什么这是点双联通分量呢?
    在一个点双联通分量里,有着像边双联通分量类似的性质,任意两点间一定存在除了起点和终点外所经过的点集互不相交的至少两条路径。
    然而这就是这道题要求的!
    求出点双联通分量后,我们还要判断这个点双联通分量是不是能构成奇环,而有奇环的图不是二分图,所以我们只要判断这个该点双联通分量是不是二分图就好了,所以对它进行黑白染色看是否有冲突。
    另外,在求点双联通分量时要注意,要从栈里取出的是到当前v的点而不是到当前u,因为有可能我在搜u的边的时候先搜索了其他的点,而那些点没有构成一个点双联通分量,所以那样取出的点集就是错误的了。至于当前割点,我们只要手动把他加至这个点集即可。
    这样这道题就算结束了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1010
    #define M 500010
    using namespace std;
    int n,m,head[N],cnt=1,t,dfn[N],low[N],sum,num,color[N],ans,vc[N],vis[N],stk[N],r;
    bool e[N][N],yes[N];
    struct hhh
    {
        int to,next;
    }edge[2*M];
    
    int read()
    {
        int ans=0,fu=1;
        char j=getchar();
        for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
        if (j=='-') j=getchar(),fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    bool dfs(int x,int t)
    {
        color[x]=t;
        for (int i=head[x],v;i;i=edge[i].next)
        {
    	v=edge[i].to;
    	if (vc[v]!=sum) continue;
    	if (vis[v]==sum && color[v]==t) return 0;
    	if (vis[v]!=sum)
    	{
    	    vis[v]=sum;
    	    if (!dfs(v,t^1)) return 0;
    	}
        }
        return 1;
    }
    
    void Tarjan(int x,int f)
    {
        dfn[x]=low[x]=++t;
        stk[r++]=x;
        for (int i=head[x],v;i;i=edge[i].next)
        {
    	v=edge[i].to;
    	if (v==f) continue;
    	if (!dfn[v])
    	{
    	    Tarjan(v,x);
    	    low[x]=min(low[v],low[x]);
    	    if (low[v]>=dfn[x])
    	    {
    		sum++;
    		num=1;
    		int tt;
    		do
    		{
    		    tt=stk[--r];
    		    vc[tt]=sum;
    		    num++;
    		}while(tt!=v);
    		vc[x]=sum;
    		if (!dfs(x,1))
    		{
    		    for (int i=r;i<r+num-1;i++) yes[stk[i]]=1;
    		    yes[x]=1;
    		}
    	    }
    	}
    	else low[x]=min(dfn[v],low[x]);
        }
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&m))
        {
    	if (n==0 && m==0) break;
    	cnt=1;
    	r=0;
    	t=sum=0;
    	ans=0;
    	memset(head,0,sizeof(head));
    	memset(dfn,0,sizeof(dfn));
    	memset(e,0,sizeof(e));
    	memset(vis,0,sizeof(vis));
    	memset(yes,0,sizeof(yes));
    	memset(vc,0,sizeof(vc));
    	for (int i=1,a,b;i<=m;i++)
    	{
    	    a=read();
    	    b=read();
    	    e[a][b]=1;
    	    e[b][a]=1;
    	}
    	for (int i=1;i<=n;i++)
    	    for (int j=1;j<=n;j++)
    		if (i!=j && e[i][j]!=1) add(i,j);
    	for (int i=1;i<=n;i++)
    	    if (!dfn[i]) Tarjan(i,0);
    	for (int i=1;i<=n;i++) if (!yes[i]) ans++;
    	printf("%d
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    redis参数AOF参数的bug
    tidb损坏tikv节点怎么恢复集群
    mysql主从延时临时解决办法
    python脚本批量杀死redis链接
    pt-online-schema-change 脚本化
    mysql查看锁等信息SQL
    mongo复制集脑裂问题如何处理
    日志收集及网络包收集方案
    各浏览器下载文件名不乱码的解决办法
    java 中 byte[]、File、InputStream 互相转换
  • 原文地址:https://www.cnblogs.com/mrha/p/7852552.html
Copyright © 2011-2022 走看看