噗...九野跟我的聊天记录==白书模板.....
开始:
开始:
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;
}