zoukankan      html  css  js  c++  java
  • poj 3683 2-sat建图+拓扑排序输出结果

    发现建图的方法各有不同,前面一题连边和这一题连边建图的点就不同,感觉这题的建图方案更好。

    题意:给出每个婚礼的2个主持时间,每个婚礼的可能能会冲突,输出方案。


    思路:n个婚礼,2*n个点,每组点是对称的,用O(n2)的方法判断每个点之间的关系来建图,然后通过拓扑排序输出即可。



    代码:

    #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];
    int a[MAXN][2],b[MAXN][2],flag[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 print(int t)
    {
     	int h=t/60,m=t%60;
     	printf("%02d:%02d",h,m);
    }
    
    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<n;i++)            //有2n个点 2*i 代表起始时间  2*i+1代表结束时间
    	{
    		for(int j=i+1;j<n;j++)
    		{
    			if((a[i][1]-a[j][0])*(a[i][0]-a[j][1])<0)  //前 前冲突
    			{
    				addedge(i*2,2*j+1);
    				addedge(j*2,2*i+1);
    			}
    			if((a[i][1]-b[j][0])*(a[i][0]-b[j][1])<0)  //前 后
    			{
    				addedge(i*2,2*j);
    				addedge(j*2+1,2*i+1);
    			}
    			if((b[i][1]-b[j][0])*(b[i][0]-b[j][1])<0)  //后后
    			{
    				addedge(2*i+1,2*j);
    				addedge(2*j+1,2*i);
    			}
    			if((b[i][1]-a[j][0])*(b[i][0]-a[j][1])<0)   //后前
    			{
    				addedge(2*i+1,2*j+1);
    				addedge(2*j,2*i);
    			}
    		}
    	}
    }
    void solve()
    {
    	memset(dfn,0,sizeof(dfn));
    	memset(instack,0,sizeof(instack));
    	index=0;scnt=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[2*i]==fa[2*n+1])   //冲突
    		{
    			return 0;
    		}
    	}
    	return 1;
    }
    void topsort()
    {
    
    	for(int i=0;i<scnt;)
    	{
    		for(int j=1;j<=scnt;j++)
    		{
    			if(!in[j])
    			{
    				in[j]--;ans[i++]=j;
    				for(int k=first[j];k!=-1;k=e[k].next)
    				{
    					int v=e[k].v;
    					in[v]--;
    				}
    			}
    		}
    	}
    		memset(flag,0,sizeof(flag));
    		for(int i=0;i<scnt;i++)
    		{
    			for(int j=0;j<2*n;j++)
    			{
    				if(fa[j]==ans[i]&&!flag[j^1])
    					{
    
    						flag[j]=1;
    					}
    			}
    		}
    		for(int i=0;i<2*n;i++)
    		{
    			if(flag[i])
    			{
    				if(i%2==0)
    				{
    					print(a[i/2][0]);printf(" ");print(a[i/2][1]);printf("
    ");
    				}
    				else
    				{
    					print(b[i/2][0]);printf(" ");print(b[i/2][1]);printf("
    ");
    				}
    			}
    		}
    }
    int main()
    {
    		scanf("%d",&n);
    		memset(head,-1,sizeof(head));tot=0;
    		memset(first,-1,sizeof(first));tt=0;
    		for(int i=0;i<n;i++)
    		{
    			int t1,t2;
    			scanf("%d:%d",&t1,&t2);
    			a[i][0]=t1*60+t2;
    			scanf("%d:%d",&t1,&t2);
    			b[i][1]=t1*60+t2;
    			scanf("%d",&time);
    			a[i][1]=a[i][0]+time;
    			b[i][0]=b[i][1]-time;
    		}
    		build();
    		solve();
    		if(!check())printf("NO
    ");
    		else
    		{
    			memset(in,0,sizeof(in));
    			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]]++;
    					}
    				}
    			}
    			printf("YES
    ");
    			topsort();
    		}
    
    	return 0;
    }
    


  • 相关阅读:
    Windows下MySQL多实例运行
    Java中,什么时候用logger.debuge,info,error
    乒乓球(Table Tennis)
    [Delphi]Delphi学习
    [CALL]01
    [转自看雪]新手学习计划
    [JAVA]函数
    [1.1]
    [SQL]课堂记录
    [SYS]VS2010驱动开发配置
  • 原文地址:https://www.cnblogs.com/amourjun/p/5134106.html
Copyright © 2011-2022 走看看