2 - SAT
解决例如 $\mathrm{x}$ 或 $\mathrm{y}$ 其中一个需要成立的问题.
处理这种问题的时候对于每个点建立真和假.
然后就连一下边就行,特别注意这个边是有对称性的.
所以如果每次只连了一种边就要注意是否没考虑周全.
在输出答案的时候显然可以用是否在一个联通分量内来判合法性.
然后如果合法的话对于 $\mathrm{x}$ 点选择拓扑序靠后的决策.
#include <cstdio>
#include <stack>
#include <algorithm>
#include <cstring>
#include <vector>
#define N 2000009
#define ll long long
#define pb push_back
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
vector<int>G[N];
stack<int>S;
int n,m,tot,id[N][2],cnt,scc,low[N],dfn[N], col[N];
void tarjan(int x) {
S.push(x);
low[x]=dfn[x]=++scc;
for(int i=0;i<G[x].size();++i) {
int v=G[x][i];
if(!dfn[v]) {
tarjan(v);
low[x]=min(low[x], low[v]);
}
else if(!col[v]) {
low[x]=min(low[x], dfn[v]);
}
}
if(low[x] == dfn[x]) {
++tot;
for(;;) {
int p = S.top();
S.pop();
col[p] = tot;
if(p == x) {
break;
}
}
}
}
int main() {
// setIO("input");
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) {
id[i][0]=++cnt;
id[i][1]=++cnt;
}
for(int i=1;i<=m;++i) {
int x,a,y,b;
scanf("%d%d%d%d",&x,&a,&y,&b);
G[id[x][a ^ 1]].pb(id[y][b]);
G[id[y][b ^ 1]].pb(id[x][a]);
}
for(int i=1;i<=cnt;++i) {
if(!dfn[i]) {
tarjan(i);
}
}
int flag = 0;
for(int i = 1; i <= n ; ++ i) {
if(col[id[i][0]] == col[id[i][1]]) {
flag = 1;
break ;
}
}
if(flag) {
printf("IMPOSSIBLE\n");
}
else {
printf("POSSIBLE\n");
for(int i = 1; i <= n ; ++ i) {
if(col[id[i][0]] < col[id[i][1]]) {
// dfn 在前,拓扑序在后.
printf("0 ");
}
else {
printf("1 ");
}
}
}
return 0;
}
满汉全席
来源:luoguP4171 [JSOI2010] 满汉全席
直接建个图跑一个 2 - SAT 就行了.
然后这道题的读入就比较恶心,char 和 int 连一起 ......
注意一下读入即可.
#include <cstdio>
#include <vector>
#include <stack>
#include <cstring>
#include <algorithm>
#define N 2009
#define ll long long
#define pb push_back
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,m,cnt,id[N][2],col[N],tot,low[N],dfn[N],scc;
vector<int>G[N];
stack<int>S;
void tarjan(int x) {
S.push(x);
low[x]=dfn[x]=++scc;
for(int i=0;i<G[x].size();++i) {
int v=G[x][i];
if(!dfn[v]) {
tarjan(v);
low[x]=min(low[x], low[v]);
}
else if(!col[v]) {
low[x]=min(low[x], dfn[v]);
}
}
if(low[x]==dfn[x]) {
++tot;
for(;;) {
int p = S.top();
S.pop();
col[p] = tot;
if(p == x) {
break;
}
}
}
}
void solve() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) {
id[i][0] = ++ cnt;
id[i][1] = ++ cnt;
}
for(int i=1;i<=m;++i) {
char c;
int x,a,y,b;
scanf("%c",&c);
while(c == ' ' || c == '\n') scanf("%c",&c);
if(c == 'm') a = 0;
else a = 1;
scanf("%d", &x);
scanf("%c",&c);
while(c == ' ' || c == '\n') scanf("%c",&c);
if(c == 'm') b = 0;
else b = 1;
scanf("%d",&y);
G[id[x][a ^ 1]].pb(id[y][b]);
G[id[y][b ^ 1]].pb(id[x][a]);
}
for(int i=1;i<=cnt;++i) {
if(!dfn[i]) {
tarjan(i);
}
}
int flag = 0;
for(int i=1;i<=n;++i) {
if(col[id[i][0]] == col[id[i][1]]) {
flag = 1;
}
}
if(flag) {
printf("BAD\n");
}
else {
printf("GOOD\n");
}
cnt = scc = tot = 0;
for(int i = 1; i <= 2 * n ; ++ i) {
low[i] = dfn[i] = 0;
G[i].clear();
col[i] = 0;
id[i][0]=id[i][1]=0;
}
while(!S.empty()) {
S.pop();
}
}
int main() {
// setIO("input");
int T;
scanf("%d",&T);
while(T--) solve() ;
return 0;
}

浙公网安备 33010602011771号