HDU 3062 Party(2-SAT简单题)
http://acm.hdu.edu.cn/showproblem.php?pid=3062
题意:
有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
分析:
2-sat简单题,直接按题意求解即可.每对夫妻代表图中的一个节点,该节点有0或1两种选择.
如果对于矛盾关系 a b 0 1(表示第a对夫妻的妻子与第b对夫妻的丈夫有矛盾)
则要添加边 add_clause(a,0,b,0) 且 add_clause(b,1,a,1).
看最终本2-SAT问题是否有解。
AC代码:
#include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn= 1000+10; struct TwoSAT { int n; vector<int> G[maxn*2]; int S[maxn*2],c; bool mark[maxn*2]; bool dfs(int x) { if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; S[c++]=x; for(int i=0;i<G[x].size();i++) if(!dfs(G[x][i])) return false; return true; } void init(int n) { this->n=n; for(int i=0;i<n*2;i++) G[i].clear(); memset(mark,0,sizeof(mark)); } void add_clause(int x,int xval,int y,int yval) { x=x*2+xval; y=y*2+yval; G[x].push_back(y); } bool solve() { for(int i=0;i<2*n;i+=2) if(!mark[i] && !mark[i+1]) { c=0; if(!dfs(i)) { while(c>0) mark[S[--c]]=false; if(!dfs(i+1)) return false; } } return true; } }TS; int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { TS.init(n); while(m--) { int a,b,va,vb; scanf("%d%d%d%d",&a,&b,&va,&vb); TS.add_clause(a,va,b,vb^1); TS.add_clause(b,vb,a,va^1); } printf("%s\n",TS.solve()?"YES":"NO"); } return 0; }