lightoj 1407 2-sat
这题的英语either...or....很蛋疼;
m中,1:x与y至少一个出席;2:x出席,y随便,x不出席,y也不出席----这有个坑,可以推出y出席x也一定出席(这个关系必须要连上);3x与y至少一个不出席 4,x与y有且只有一个出席。
对于k中的数据:我琢磨很久,关系在图上是建不了的,type为1时三个人至少有一个人要出席,则三个都不出席的情况是不允许的,dfs的时候判断一下就是了,同理type为2的情况。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<queue> #include<vector> using namespace std; const int maxn = 1310; const int maxe = 100000; const int INF = 0x3f3f3f; int n,m,k; struct node{ int type,x,y,z; }a[6]; struct TwoSat{ int n; int mark[maxn*2]; int s[maxn*2],cnt; vector<int> G[maxn*2]; void init(int n){ this->n = n; for(int i=2;i<=2*n+1;i++) G[i].clear(); memset(mark,0,sizeof(mark)); } void add_clause1or3(int u,int uval,int v,int vval){ u = u*2 + uval; //u与v不共存; v = v*2 + vval; G[u].push_back(v^1); G[v].push_back(u^1); } void add_clause2(int u,int uval,int v,int vval){ u = u*2 + uval; v = v*2 + vval; G[u].push_back(v); G[v^1].push_back(u^1); } void add_clause4(int u,int uval,int v,int vval){ u = u*2 + uval; v = v*2 + vval; G[u^1].push_back(v); G[u].push_back(v^1); G[v^1].push_back(u); G[v].push_back(u^1); } bool JudgeWrong(){ for(int i=0;i<k;i++){ if(a[i].type == 1){ int x = 2*a[i].x+1,y = 2*a[i].y+1,z = 2*a[i].z+1; if(mark[x] && mark[y] && mark[z]) return true; } if(a[i].type == 2){ int x = 2*a[i].x,y = 2*a[i].y,z = 2*a[i].z; if(mark[x] && mark[y] && mark[z]) return true; } } return false; } bool dfs(int u){ if(mark[u^1]) return false; if(mark[u]) return true; mark[u] = true; s[cnt++] = u; if(JudgeWrong()) return false; for(int i=0;i<G[u].size();i++) if(!dfs(G[u][i])) return false; return true; } bool solve(){ for(int i=2;i<=2*n;i+=2) if(!mark[i] && !mark[i+1]){ cnt = 0; if(!dfs(i)){ while(cnt > 0) mark[s[--cnt]] = false; //要回溯; if(!dfs(i+1)) return false; } } return true; } void print(){ int ans[maxn],pv = 0; for(int i=2;i<=2*n;i+=2) if(mark[i]) ans[pv++] = i/2; printf("%d",pv); for(int i=0;i<pv;i++) printf(" %d",ans[i]); printf(".\n"); } }solver; int main() { //freopen("E:\\acm\\input.txt","r",stdin); int T; cin>>T; for(int t=1;t<=T;t++){ scanf("%d %d %d",&n,&m,&k); solver.init(n); for(int i=1;i<=m;i++){ int type,x,y; scanf("%d %d %d",&type,&x,&y); if(type == 1) solver.add_clause1or3(x,1,y,1); else if(type == 2) solver.add_clause2(x,1,y,1); else if(type == 3) solver.add_clause1or3(x,0,y,0); else solver.add_clause4(x,0,y,0); } for(int i=0;i<k;i++) scanf("%d %d %d %d",&a[i].type,&a[i].x,&a[i].y,&a[i].z); if(solver.solve()){ printf("Case %d: Possible ",t); solver.print(); } else printf("Case %d: Impossible.\n",t); } }