2-sat

简单概括一下2-sat:

给定一个布尔方程判断是否存在一组变量的真值指派是方程为真。特别地,求解形如(a∨b)∧(c∨d)∧...的方程为2-sat。

 

How to?

把每一个(a∨b)改写为(!a=>b∧!b=>a)的样子(...你们凑合着看吧,那个=>是蕴涵的意思),然后根据蕴涵的关系连边,再求一发强连通分量,如果a和!a在同一个强连通分量就无解,否则:若x所在强连通分量的拓扑序在!x之后就令x为真,是一组合法的解。

 

QAQ还是给一段代码吧..感觉这代码真是丑得不忍直视

连边:(摘自poj3683)

 

for(i=1;i<=n;i++)
	for(j=1;j<=n;j++)
		if(i!=j)
		{
			if(!(t[i]<=s[j]||t[j]<=s[i])) 
				{a[i].push_back(j+n);a[j].push_back(i+n);}
			if(!(t[i]<=s[j+n]||t[j+n]<=s[i])) 
				{a[i].push_back(j);a[j+n].push_back(i+n);}
			if(!(t[i+n]<=s[j]||t[j]<=s[i+n])) 
				{a[i+n].push_back(j+n);a[j].push_back(i);}
			if(!(t[i+n]<=s[j+n]||t[j+n]<=s[i+n])) 
				{a[i+n].push_back(j);a[j+n].push_back(i);}
		}


判断:(还是摘自poj3683)

 

 

	for(i=1;i<=n;i++)
		if(v[i]==v[i+n]) {printf("NO\n");return 0;}
	printf("YES\n");
	for(i=1;i<=n*2;i++) b[i].clear();
	for(i=1;i<=n*2;i++)
		for(j=0;j

 

 

 

 

 

 

题目:

 

 

 

你可能感兴趣的:(一些(玄学的)知识,图论)