Ural 1382 2SAT

ural1382 直接套用 2SAT模板

缩点 拓扑排序。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
//2SAT问题  准确判断矛盾边 不必考虑推出的边是否存在矛盾!!
using namespace std;
const int maxn=(1000+1);
vector<int>po[maxn*2],ps[maxn*2],strong[maxn*2];
bool vis[maxn*2],added[maxn*2][maxn*2];
int n,a[maxn],b[maxn],c[maxn],tot=0,color[maxn*2],du[maxn*2],point[maxn*2];
stack<int>s;
void add(int b,int a)
{
 if(added[b][a])return;
 	else added[b][a]=true;
 po[a].push_back(b);
 ps[b].push_back(a);
}
void dfs1(int cur,int fa)
{
 vis[cur]=true;
 for(int i=0;i<po[cur].size();i++)
 	{
 	 int np=po[cur][i];
	 if(np==fa||vis[np])continue;
	 dfs1(np,cur);
	}
 s.push(cur);
}
void  dfs2(int cur,int co,int fa)
{
 strong[co].push_back(cur);
 color[cur]=co;
 for(int i=0;i<ps[cur].size();i++)
 	{
 	 int np=ps[cur][i];
 	 if(np==fa||(color[np]))continue;
 	 dfs2(np,co,cur);
	}
}
void strongconnect()
{
 memset(vis,0,sizeof(vis));memset(color,0,sizeof(color));
 for(int i=1;i<=n*2;i++)
    if(!vis[i])dfs1(i,-1);
 tot=1;
 while(!s.empty())
 	{
 	 int np=s.top();
 	 s.pop();
 	 if(color[np])continue;
 	 dfs2(np,tot++,-1);
	}
}
bool cmp(int a,int b)
{
 return du[a]<du[b];
}
int  topo(int ans[])
{
 for(int i=1;i<tot;i++)
 	point[i]=i;
 bool anss=1;
 for(int i=1;i<tot;i++)
 	{
 	 sort(point+i,point+tot,cmp);
 	 int np=point[i];
 	 if(du[np]>0)return -1;
 	 if(du[np]==du[point[i+1]]&&i+1<tot)anss=0;
 	 ans[i]=np;
 	 for(int j=0;j<ps[np].size();j++)
 	 	du[ps[np][j]]--;
	}
}
int main()
{
 freopen("t.txt","r",stdin);
 scanf("%d",&n);
 for(int i=1;i<=n;i++)
 	scanf("%d%d%d",&a[i],&b[i],&c[i]);
 for(int i=1;i<=n;i++)
 	for(int j=1;j<=n;j++)
 		{
 		 if(i==j)continue;
 		 if(a[i]==a[j])
 		 	{
 		 	 add(j*2,i*2-1);
 		 	 add(i*2,j*2-1);
			}
		 if(i==b[j])
		 	{
		 	 add(i*2,j*2);
		 	 add(j*2-1,i*2-1);
			}
		 if(b[i]==b[j])
		 	{
		 	 add(i*2-1,j*2);
		 	 add(j*2-1,i*2);
			}
		 if((a[i]==c[j]&&i!=b[j]))
		 	{
		 	 add(i*2,j*2);
		 	 add(j*2-1,i*2-1);
			}
		}
 strongconnect();

 for(int i=1;i<tot;i++)
 	{
 	 memset(vis,0,sizeof(vis));
 	 ps[i].clear();
 	 for(int j=0;j<strong[i].size();j++)
 	 	{
 	 	 int np=strong[i][j];
 	 	 for(int k=0;k<po[np].size();k++)
 	 	 	{
 	 	 	 int nc=color[po[np][k]];
 	 	 	 if(nc==i)continue;
 	 	 	 if(vis[nc]){continue;}
 	 	 	 	else{vis[nc]=true;ps[i].push_back(nc);du[nc]++;}
			}
		}
	}
 int ans[maxn*2];
 topo(ans);
 int anss[maxn];
 for(int i=	tot-1;i>=1;i--)
 	{
 	 int np=ans[i];
 	 for(int i=0;i<strong[np].size();i++)
 	 	{
 	 	 int npp=strong[np][i];
 	 	if(anss[(npp+1)/2]==0) anss[((npp+1)/2)]=(npp+1)%2+1;
		}
	}
 for(int i=1;i<n;i++)
 	printf("%d ",anss[i]);
 printf("%d\n",anss[n]);
  return 0;
}

  

时间: 2024-08-17 12:04:01

Ural 1382 2SAT的相关文章

【2-SAT】URAL - 2089 - Experienced coach

题意:给出n对点a,b  要求从没对点中选出一个,且最终选出的点n个数不能存在相同的.输入数据满足每种数最多出现3次,最少出现1次 思路:第i对点的编号2*i, 2*i+1,   因为每个数最多出现3次,那么完全可以枚举每个数,然后相同的数之间的编号建立关系(?a Λ ?b 为真,表示这两个编号不能同时选), 然后同一对的俩编号之间也有关系(a xor b为真,代表a和b必须选且只能选一个,a xor b 可以写成 (a V b) Λ (?a V ?b)),这样跑完twosat就能得到一个满足情

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

【BZOJ】1382: [Baltic2001]Mars Maps (线段树+扫描线)

1382: [Baltic2001]Mars Maps Time Limit: 5 Sec  Memory Limit: 64 MB Description 给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并 Input 先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标. Output 输出面积并 Sample Input 2 10 10 20 20 15 15 25 30 Sample Output 225 本以为是傻逼题,没想到不容易啊- 线段树+扫描

Uva 1391 (LA 3713) Astronauts (2-SAT问题)

今天学了2-SAT问题,就找了这道例题,敲了一下,还好过了. 2-SAT问题应该是把一些布尔变量之间的逻辑关系反映到一个无向图(有时可能是有向图)上来.通过推导的形式在这个有向图里面补边.再通过确定一些变量的值,使所有的变量都能符合题意中逻辑关系.补边方式 即如果Xi = true && Xj = false 不符合题意,那么如果Xi == true ,那么就在 Xi = true 和 Xj = true之间连一条边, 使得当Xi = true 时能马上确定 Xj = true. 在实际操

BZOJ 1823: [JSOI2010]满汉全席( 2-sat )

2-sat...假如一个评委喜好的2样中..其中一样没做, 那另一样就一定要做, 这样去建图..然后跑tarjan. 时间复杂度O((n+m)*K) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using na

HDU 4115 Eliminate the Conflict【2-sat】

转载请注明出处:http://blog.csdn.net/u013912596 题目大意: Alice和Bob玩若干轮石头剪刀布的游戏,Alice已经知道了Bob在每一轮会出什么,但是Bob会给出一些Alice的限制条件,问Alice在不打破这些限制的情况下,有没有可能赢. 限制格式为(i,j,w),i,j代表第几轮,w=1的话,要求Alice在第i轮和第j轮的策略不能相同,w=0的话,要求Alice在第i轮和第j轮的策略必须相同. 思路: 刚开始以为这个题是个DP,按照这个想了一下,发现要求相

Ural 1081 Binary Lexicographic Sequence(DP)

题目地址:Ural 1081 先用dp求出每个长度下的合法序列(开头为1)的个数.然后求前缀和.会发现正好是一个斐波那契数列.然后每次判断是否大于此时长度下的最少个数,若大于,说明这一位肯定是1,若小于,则肯定是0.就这样不断输出出来即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #in

URAL 1684. Jack&#39;s Last Word KMP

题目来源:URAL 1684. Jack's Last Word 题意:输入a b 把b分成若干段 每一段都是a的前缀 思路:b为主串 然后用a匹配b 记录到b的i位置最大匹配的长度 然后分割 分割的时候要从后往前 如果a = abac b = abab 那么如果从前往后 首先覆盖了aba 然后b就不能覆盖了 从后往前就可以了 首先覆盖ab 下一次还是ab 因为已经记录了到i位置的最大匹配长度 根据长度从末尾倒退 每次倒退的时候只要是最大的匹配的长度 因为如果在某一次的递推 记录的最大匹配的前缀

HDU 4421 Bit Magic(2-sat)

HDU 4421 Bit Magic 题目链接 题意:就依据题目,给定b数组.看能不能构造出一个符合的a数组 思路:把每一个数字的每一个二进制位单独考虑.就变成一个2-sat题目了,依据题目中的式子建立2-sat的边.然后每一位跑2-sat.假设每位都符合.就是YES,假设有一位不符合就是NO 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #incl