2-sat
Posted starve
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2-sat相关的知识,希望对你有一定的参考价值。
提:http://acm.hdu.edu.cn/showproblem.php?pid=3062
题目思路:
对于这类问题一般的解法为将每个点分为 x 和 x‘ 分别表示每组当中的两种状态,这里表示丈夫和妻子,然后更具定义我们建图,如果 A和B有矛盾则选A必选B‘,选B必选A‘ ,所以我们对该图缩点,如果A和A‘属于同一个环当中则说明选A必选A‘,所以不存在,否则就存在
#include<vector> #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define pb push_back const int M=5000; vector<int>g[M]; int low[M],dfn[M],sta[M],vis[M],cmp[M]; int tot,cnt,top; void tarjan(int u){ low[u]=dfn[u]=++cnt; sta[++top]=u; vis[u]=1; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ tot++; cmp[u]=tot; vis[u]=0; while(sta[top]!=u){ cmp[sta[top]]=tot; vis[sta[top--]]=0; } top--; } } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i=0;i<=2*n;i++) g[i].clear(),low[i]=dfn[i]=cmp[i]=vis[i]=sta[i]=0; top=cnt=tot=0; while(m--){ int a1,a2,c1,c2; scanf("%d%d%d%d",&a1,&a2,&c1,&c2); int a = a1*2+c1; int b = a2*2+c2; g[a].pb(b^1); // cout<<u<<"----"<<2*a2+(1-c2)<<endl; // g[2*a2+(1-c2)].pb(u); g[b].pb(a^1); // cout<<v<<"----"<<2*a1+(1-c1)<<endl; // g[2*a1+(1-c1)].pb(v); } for(int i=0;i<2*n;i++) if(!dfn[i]) tarjan(i); int flag=1; for(int i=0;i<n;i++){ if(cmp[2*i]==cmp[2*i+1]){ flag=0; break; } } if(flag) puts("YES"); else puts("NO"); } return 0; }
以上是关于2-sat的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3905 Perfect Election(2-sat)