标签:
这篇从原理上理解2-sat如何转化成图论问题简述了如何了实现算法:http://wenku.baidu.com/view/31fd7200bed5b9f3f90f1ce2.html
总的来说2-sat有两种算法,一种用dfs染色搜索出一种解,一种用tarjan(判定是否有解)+拓扑排序构造出任意一个可行解。
dfs从理论上复杂度很高,但是实际上远远达不到上界,而且可以按字典序搜索,实现也简单多了
有n个候选人,m组要求,每组要求关系到候选人中的两个人,“+i +j”代表i和j中至少有一人被选中,“-i -j”代表i和j中至少有一人不被选中。“+i -j”代表i被选中和j不被选中这两个事件至少发生一个,“-i +j”代表i不被选中和j被选中这两个事件至少发生一个。问是否存在符合所有m项要求的方案存在。
思路:每个人是两种情况,选中和不选中,根据每种关系都可以建有向边,果果的2-sat
dfs判解:
//12384K 1704MS #include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int N = 2020; vector<int>g[N]; int n,m; bool mark[N]; int sta[N],top; inline void add_edge(int u,int c1,int v,int c2) { u=2*(u-1)+c1,v=2*(v-1)+c2; g[u^1].push_back(v); g[v^1].push_back(u); } bool dfs(int u) { if(mark[u^1]) return false; if(mark[u]) return true; mark[u]=1; sta[++top]=u; int sz=g[u].size(); for(int i=0;i<sz;i++) { int v=g[u][i]; if(dfs(v)==false) return false; } return true; } bool judge() { for(int i=0;i<n;i++) { if(!mark[i]&&!mark[i^1]) { top=0; if(dfs(i)==false) { for(int j=1;j<=top;j++) mark[sta[j]]=0; top=0; if(dfs(i^1)==false) return false; } } } return true; } void ini() { for(int i=0;i<n;i++) g[i].clear(); memset(mark,0,sizeof(mark)); top=0; } int main() { while(~scanf("%d%d",&n,&m)) { n*=2; ini(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); if(u>0&&v>0) add_edge(u,1,v,1); if(u<0&&v>0) add_edge(-u,0,v,1); if(u<0&&v<0) add_edge(-u,0,-v,0); if(u>0&&v<0) add_edge(u,1,-v,0); } if(judge()) puts("1"); else puts("0"); } return 0; }
//12436K 1672MS C++ 1673B #include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int N = 2020; vector<int>g[N]; int dfn[N],low[N]; int sta[N],top; int index; int tmp[N]; int n,m; inline void add_edge(int u,int c1,int v,int c2) { u=2*(u-1)+c1,v=2*(v-1)+c2; g[u^1].push_back(v); g[v^1].push_back(u); } void tarjan(int u) { dfn[u]=low[u]=++index; tmp[u]=1; sta[++top]=u; int sz=g[u].size(); for(int i=0;i<sz;i++) { int v=g[u][i]; if(tmp[v]==0) tarjan(v); if(tmp[v]==1) low[u]=min(low[u],low[v]); } if(dfn[u]==low[u]) { do { int v=sta[top]; tmp[v]=2; }while(sta[top--]!=u); } } void ini() { for(int i=0;i<n;i++) g[i].clear(); memset(tmp,0,sizeof(tmp)); index=top=0; } int main() { while(~scanf("%d%d",&n,&m)) { n*=2; ini(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); if(u>0&&v>0) add_edge(u,1,v,1); if(u<0&&v>0) add_edge(-u,0,v,1); if(u<0&&v<0) add_edge(-u,0,-v,0); if(u>0&&v<0) add_edge(u,1,-v,0); } for(int i=0;i<n;i++) if(!tmp[i]) tarjan(i); int ans=1; for(int i=0;i<n;i++) if(low[i]==low[i^1]) ans=0; printf("%d\n",ans); } return 0; }
POJ 3905 Perfect Election (初学2-Sat)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/45228607