zoukankan      html  css  js  c++  java
  • poj 3648 2-SAT建图+topsort输出结果

    其实2-SAT类型题目的类型比较明确,基本模型差不多是对于n组对称的点,通过给出的限制条件建图连边,然后通过缩点和判断冲突来解决问题。要注意的是在topsort输出结果的时候,缩点后建图需要反向连边,然后输出就可以了。2-sat题型差不多。

    题意:新娘新郎分别坐在长桌两边,n-1队夫妇来参加婚礼,要求:夫妇不能坐在同一边,通奸关系不能坐在同一边。输出新娘对面的序列。

    思路:对称关系:夫妇,限制条件:通奸关系。基础2-sat问题,缩点找冲突topsort输出结果一气呵成。。。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MAXN 2002
    int instack[MAXN],stack[MAXN],fa[MAXN],vis[MAXN],head[MAXN],first[MAXN];
    int dfn[MAXN],low[MAXN],in[MAXN],ans[MAXN],que[MAXN];
    int a[MAXN][2],b[MAXN][2],flag[MAXN],cf[MAXN],col[MAXN];
    int n,m,tot,scnt,time,tt,top,index;
    
    struct Edge
    {
    	int v,next;
    }edge[MAXN*MAXN],e[MAXN*MAXN];
    
    void addedge(int u,int v)
    {
    	edge[tot].v=v;
    	edge[tot].next=head[u];
    	head[u]=tot++;
    }
    void adde(int u,int v)
    {
    	e[tt].v=v;
    	e[tt].next=first[u];
    	first[u]=tt++;
    }
    void tarjan(int u)
    {
    	instack[u]=1;
    	stack[top++]=u;
    	dfn[u]=low[u]=++index;
    	int v;
    	for(int i=head[u];i!=-1;i=edge[i].next)
    	{
    		v=edge[i].v;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}
    		else if(instack[v])
    		{
    			low[u]=min(low[u],dfn[v]);
    		}
    	}
    	if(low[u]==dfn[u])
    		{
    			scnt++;
    			do
    			{
    				v=stack[--top];
    				instack[v]=0;
    				fa[v]=scnt;
    			}while(v!=u);
    		}
    }
    void build()
    {
    	for(int i=0;i<m;i++)          //2*n的点
    		{
    			int t1,t2;char c,v;
    			scanf("%d%c",&t1,&c);
    			scanf("%d%c",&t2,&v);
    			if(c=='h'&&v=='h')
    			{
    				addedge(t1+n,t2);
    				addedge(t2+n,t1);
    			}
    			else if(c=='h'&&v=='w')
    			{
    				addedge(t1+n,t2+n);
    				addedge(t2,t1);
    			}
    			else if(c=='w'&&v=='h')
    			{
    				addedge(t1,t2);
    				addedge(t2+n,t1+n);
    			}
    			else if(c=='w'&&v=='w')
    			{
    				addedge(t1,t2+n);
    				addedge(t2,t1+n);
    			}
    		}
    		addedge(0,n);
    }
    void solve()
    {
    	memset(dfn,0,sizeof(dfn));
    	memset(instack,0,sizeof(instack));
    	index=0;scnt=0;top=0;
    	for(int i=0;i<2*n;i++)
    	{
    		if(!dfn[i])
    			tarjan(i);
    	}
    }
    int check()
    {
    	for(int i=0;i<n;i++)
    	{
    		if(fa[i]==fa[i+n])   //冲突
    		{
    			return 0;
    		}
    		cf[fa[i]]=fa[i+n];
    		cf[fa[i+n]]=fa[i];
    	}
    	return 1;
    }
    void topsort()
    {
    	int head=1,tail=1;
    	for(int i=1;i<=scnt;i++)
    	{
    		if(in[i]==0)
    		{
    			que[tail++]=i;
    		}
    	}
    	int v;
    	while(tail>head)
    	{
    		int u=que[head];
    		head++;
    		if(col[u]==0)     //对于未着色的点x,将x染成红色1,同时将与x矛盾的点cf[x]染成蓝色-1。
    		{
    			col[u]=1;
    			col[cf[u]]=-1;
    		}
    		for(int i=first[u];i!=-1;i=e[i].next)
    		{
    			v=e[i].v;
    			if(--in[v]==0)
    			{
    				que[tail++]=v;
    			}
    		}
    	}
    	memset(ans,0,sizeof(ans));
    		for(int i=0;i<n;i++)
    		{
    			if(col[fa[i]]==1)
    			{
    				ans[i]=1;
    			}
    		}
    		for(int i=1;i<n;i++)
    		{
    			if(ans[i])
    				printf("%dh ",i);
    			else
    				printf("%dw ",i);
    		}
    		printf("
    ");
    }
    int main()
    {
    	while(scanf("%d%d",&n,&m)!=EOF,(n||m))
    	{
    		memset(head,-1,sizeof(head));tot=0;
    		memset(first,-1,sizeof(first));tt=0;
    
    		build();
    		solve();
    		if(!check())printf("bad luck
    ");
    		else
    		{
    			memset(in,0,sizeof(in));
    			memset(col,0,sizeof(col));
    			for(int i=0;i<2*n;i++)
    			{
    				int v;
    				for(int j=head[i];j!=-1;j=edge[j].next)
    				{
    					v=edge[j].v;
    					if(fa[i]!=fa[v])
    					{
    						adde(fa[v],fa[i]);
    						in[fa[i]]++;
    					}
    				}
    			}
    			topsort();
    		}
    	}
    	return 0;
    }
    


     

  • 相关阅读:
    thinkphp--标签库
    thinkphp中的参数绑定
    thinkphp3.2.3子查询中遇到的错误
    开篇马克
    BST树、B-树、B+树、B*树
    linux shell编程之变量和bash配置文件(第一篇)
    linux awk进阶篇
    linux awk(gawk)
    linux sed命令
    linux basic
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134105.html
Copyright © 2011-2022 走看看