看到HDOJ上有一个2-SAT专题,刷完之后顺便总结一下。
最简单的2-SAT问题就是判断是否有解,回答YES或NO就行了,不需要输出具体的解。这种问题建图完毕后一个SCC(强连通分量)就好了。如果要输出解,就多一个拓扑排序。代码中涉及多次建图,注意细节就好了。
很裸的2-SAT模板,而且不用输出路径。
#include
#include
#include
#include
#include
#include
这个题要求输出一组解,另外需要根据区间的交来建图,代码比较长。判断区间是否相交时我先排序,这样内层循环不用遍历所有j,不过效率其实差不多,只快了一点点。。。
#include
#include
#include
#include
#include
#include
和上题差不多的。
#include
#include
const int maxn=10010;
int n, m, nxt[maxn], head[maxn], pnt[maxn], ne, e, a, b, a0, b0;
char c1, c2;
int nnxt[maxn], nhead[maxn], npnt[maxn];
int order[maxn], norder, id[maxn], v[maxn];
int ans[maxn], op[maxn];
void dfs(int d){
v[d] = 1;
for(int i=head[d]; i!=-1; i=nxt[i])
if(!v[pnt[i]])
dfs(pnt[i]);
order[norder++] = d;
}
void ndfs(int d, int k){
v[d] = 1;
id[d] = k;
for(int i=nhead[d]; i!=-1; i=nnxt[i])
if(!v[npnt[i]])
ndfs(npnt[i], k);
}
void addedge(int s, int t){
pnt[e] = t; nxt[e] = head[s]; head[s] = e++;
}
void addnedge(int t, int s){
npnt[ne] = s; nnxt[ne] = nhead[t]; nhead[t] = ne++;
}
void color(int d){
ans[d] = 2;
for(int i=head[d]; i!=-1; i=nxt[i])
if(!ans[pnt[i]])
color(pnt[i]);
}
int main(){
while(1){
norder = e = ne = 0;
memset(head, -1, sizeof head);
memset(nhead, -1, sizeof nhead);
scanf("%d%d", &n, &m);
if(!n&&!m)
break;
for(int i=0; i
=0; --i)
if(!v[order[i]])
ndfs(order[i], k++);
int mark = 1;
for(int i=0; i
=0; --i)
if(!ans[order[i]]){
ans[order[i]] = 1;
color(op[order[i]]);
}
for(int i=1; i
二分答案之后判断2-SAT问题是否有解。SCC用tarjan写的。
#include
#include
#include
#include
#include
#include
5.POJ 3207 Ikki's Story IV - Panda's Trick
也是只需要判断,不过注意弦相交的判断方法。
#include
#include
#include
#include
#include
#include
下面几题还没做,先给出链接