2-SAT暴力dfs模板解释|不看你会后悔的

噗...九野跟我的聊天记录==白书模板.....

开始:

 

a654889339-九野 2014/4/25 22:43:38

2-SAT,对每一个节点都有2种状态
22:43:44
水木清华 2014/4/25 22:43:44

对的

a654889339-九野 2014/4/25 22:43:53

就是当成2个物品

水木清华 2014/4/25 22:43:58



a654889339-九野 2014/4/25 22:44:23

那么这两个物品要取一个,但不能同时取

水木清华 2014/4/25 22:44:31



a654889339-九野 2014/4/25 22:44:43

最开始时这两个物品都没有取

水木清华 2014/4/25 22:44:50



a654889339-九野 2014/4/25 22:44:55

所以是这样 !mark[i] && !mark[i^1]

a654889339-九野 2014/4/25 22:45:05

然后随便取一个嘛

水木清华 2014/4/25 22:45:09



a654889339-九野 2014/4/25 22:45:19

所以就取为真的这个物品

水木清华 2014/4/25 22:45:28



a654889339-九野 2014/4/25 22:45:40

然后取了这个物品会导致有些物品必须取
22:45:56
水木清华 2014/4/25 22:45:56



a654889339-九野 2014/4/25 22:46:21

所以dfs看一下取了这个物品是否可行

水木清华 2014/4/25 22:46:30

哦 soga

a654889339-九野 2014/4/25 22:46:29

如果不可行就反悔

水木清华 2014/4/25 22:46:35

对的

a654889339-九野 2014/4/25 22:46:52

这些必须取的放到栈里

水木清华 2014/4/25 22:47:02



a654889339-九野 2014/4/25 22:47:03

不可行了就把栈里的都返回掉

a654889339-九野 2014/4/25 22:47:06

反悔

水木清华 2014/4/25 22:47:11



a654889339-九野 2014/4/25 22:47:15

这样就可以了
22:48:16
水木清华 2014/4/25 22:48:16

哦  i^1和i+1有关系么。。。。

水木清华 2014/4/25 22:48:30

你写的i^1  LRJ是i+1

a654889339-九野 2014/4/25 22:48:33

这个是看拆点的

a654889339-九野 2014/4/25 22:48:37

不一样

水木清华 2014/4/25 22:48:41



水木清华 2014/4/25 22:48:58

i^1的实际含义是啥

a654889339-九野 2014/4/25 22:48:58

i^1 就是 真假2个状态互相取对立

水木清华 2014/4/25 22:49:10

哦  soga

a654889339-九野 2014/4/25 22:49:09

lrj那个就是 真到假

水木清华 2014/4/25 22:49:28

真到假是啥意思?

a654889339-九野 2014/4/25 22:49:55

把i点拆成2个点 i*2跟 i*2+1

a654889339-九野 2014/4/25 22:50:02

用i*2表示真呗

水木清华 2014/4/25 22:50:10

嗯  了解了

水木清华 2014/4/25 22:50:15

九野解释的真棒

a654889339-九野 2014/4/25 22:50:16

所以 (i*2)^1 = (i*2+1)
22:50:25
a654889339-九野 2014/4/25 22:50:25

我也是刚学

水木清华 2014/4/25 22:50:34

聊天记录=2-SAT神解释!

a654889339-九野 2014/4/25 22:50:49



水木清华 2014/4/25 22:50:59

九野好腻害

a654889339-九野 2014/4/25 22:51:39

弱菜滚粗了

献上暴力模板:(缩点的话去看论文,好像这个时间复杂度也不错?原谅我的无知。)

#define N 1005*2
#define M 40000+5
//注意n是拆点后的大小 即 n <<= 1 N为点数(注意要翻倍) M为边数 i&1=0为i真 i&1=1为i假
struct Edge{
	int to, nex;
}edge[M];
//注意 N M 要修改
int head[N], edgenum;
void addedge(int u, int v){
	Edge E = {v, head[u]};
	edge[edgenum] = E;
	head[u] = edgenum ++;
}

bool mark[N];
int Stack[N], top;
void init(){
	memset(head, -1, sizeof(head)); edgenum = 0;
	memset(mark, 0, sizeof(mark));
}

bool dfs(int x){
	if(mark[x^1])return false;//一定是拆点的点先判断
	if(mark[x])return true;

	mark[x] = true;
	Stack[top++] = x;

	for(int i = head[x]; i != -1; i = edge[i].nex)
		if(!dfs(edge[i].to)) return false;

	return true;
}

bool solve(int n){
	for(int i = 0; i < n; i+=2)
		if(!mark[i] && !mark[i^1])
		{
			top = 0;
			if(!dfs(i))
			{
				while( top ) mark[ Stack[--top] ] = false;
				if(!dfs(i^1)) return false;
			}
		}
	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值