2-SAT
关于了解2-SAT,推荐两个地方:《由对称性解2-SAT问题》、【研究总结】2-sat问题
每次找到一个未被确定的Si,使得不存在Si Si’,选择Si及其后代节点而删除Si’及Si‘的前代节点。一定可以构造出一组可行解。
一个重要的性质是不管怎么加限制,对于任意一对Si, Si’ , Si的后代节点与Si’ 的前代节点相互对称总成立。
一类奇怪的加边是形如Si->Si’的,这条边保证了逆拓扑序时先访问到Si’,所以不会产生矛盾,图形依然对称。同时由这条边引起的环也是对称的,所以没有问题。
主要就是利用了2-SAT模型的对称性,搞出了 O(n+m) 时间复杂度的算法。
这题非常坑,输入数据里有形如1w2h这样中间没空格的,读入”%s%s”就挂了,坑了好久….好气啊好气啊
还有网上的代码为什么动不动就是一百多行啊...
#include<cstdio>
#include<queue>
#include<cstring>
#define N 200005
#define cmin(u,v) ((u)>(v)?(u)=(v):0)
using namespace std;
namespace runzhe2000
{
// 2*i wife 2*i+1 husb
char str[5];
int n, m, ecnt, pecnt, last[N], dfn[N], low[N], timer, sta[N], insta[N], stacnt, bel[N], bcnt, deg[N], col[N], conf[N];
struct edge{int next, to;}e[N<<1];
struct pdge{int a, b;}pe[N<<1];
void addedge(int a, int b)
{
pe[++pecnt] = (pdge){a, b};
e[++ecnt] = (edge){last[a], b};
last[a] = ecnt;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++timer; insta[x] = 1; sta[++stacnt] = x;
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to;
if(!dfn[y]) tarjan(y), cmin(low[x], low[y]);
else if(insta[y]) cmin(low[x], dfn[y]);
}
if(low[x] == dfn[x])
{
int y; ++bcnt;
do {bel[y = sta[stacnt--]] = bcnt; insta[y] = 0;}
while(y != x);
}
}
void clr()
{
timer = ecnt = pecnt = 0;
memset(col,0,sizeof(col)); memset(last,0,sizeof(last));
memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low));
}
void main()
{
for(; scanf("%d%d",&n,&m) && (n || m); )
{
clr(); addedge(1, 0); n--;
for(int i = 1, x, y; i <= m; i++)
{
scanf("%d%c%d%c",&x,&str[0],&y,&str[1]);
(x<<=1) |= (str[0] == 'h' ? 1 : 0);
(y<<=1) |= (str[1] == 'h' ? 1 : 0);
addedge(x^1, y); addedge(y^1, x);
}
for(int i = 0; i <= (n<<1|1); i++) if(!dfn[i]) tarjan(i);
int ok = 1; for(int i = 0; i <= n; i++)
if(bel[i<<1] == bel[i<<1|1]){puts("bad luck"); {ok=0; break;}}
else conf[bel[i<<1]] = bel[i<<1|1], conf[bel[i<<1|1]] = bel[i<<1];
if(!ok) continue;
memset(last,0,sizeof(last)); ecnt = 0;
for(int i = 1, ii = pecnt; i <= ii; i++)if(bel[pe[i].a] != bel[pe[i].b]) addedge(bel[pe[i].b], bel[pe[i].a]), ++deg[bel[pe[i].a]];
queue<int> q; for(int i = 1; i <= bcnt; i++) if(!deg[i]) q.push(i);
for(; !q.empty(); )
{
int x = q.front(); q.pop();
if(!col[x]) col[x] = 1, col[conf[x]] = -1;
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to;
if(!--deg[y])q.push(y);
}
}
for(int sc = col[bel[0]], i = 2; i <= (n<<1|1); i++) if(sc == col[bel[i]]) printf("%d%c ",i>>1,(i&1)?'h':'w'); puts("");
}
}
}
int main()
{
runzhe2000::main();
}