题意:
有n个候选人和m张选票,每张选票上有一种限制,问是否有一种让m张选票上的限制都满足的选举方案。
分析:
2-sat判断是否有解,不需输出解,标准化操作。
代码:
//poj 3905
//sep9
#include <iostream>
#include <stack>
using namespace std;
const int maxN=2024;
const int maxM=2200000;
int e,n,m,t,ecnt;
int head[maxN],ins[maxN],low[maxN],dfn[maxN];
int sol[maxN],belong[maxN];
stack<int> s;
struct Edge
{
int v,next;
}edge[maxM];
void addegde(int u,int v)
{
edge[e].v=v;edge[e].next=head[u];
head[u]=e++;
}
void dfs(int x)
{
low[x]=dfn[x]=++t;
s.push(x);
ins[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!dfn[v]){
dfs(v);
low[x]=min(low[x],low[v]);
}else if(ins[v]==1)
low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x]){
++ecnt;
int k;
do{
k=s.top();
s.pop();
ins[k]=0;
belong[k]=ecnt;
}while(dfn[k]!=low[k]);
}
}
bool two_sat()
{
memset(ins,0,sizeof(ins));
memset(dfn,0,sizeof(dfn));
while(!s.empty()) s.pop();
int i;
t=0,ecnt=0;
for(i=1;i<=2*n;++i)
if(!dfn[i])
dfs(i);
for(i=1;i<=n;++i)
if(belong[i]==belong[i+n])
return false;
return true;
}
int deal()
{
int a,b,c;
char op1[8],op2[8];
e=0;
memset(head,-1,sizeof(head));
while(m--){
scanf("%s%s",op1,op2);
sscanf(op1+1,"%d",&a);
sscanf(op2+1,"%d",&b);
if(op1[0]=='+'&&op2[0]=='+'){
addegde(a+n,b);
addegde(b+n,a);
}else if(op1[0]=='-'&&op2[0]=='-'){
addegde(a,b+n);
addegde(b,a+n);
}else if(op1[0]=='+'&&op2[0]=='-'){
addegde(a+n,b+n);
addegde(b,a);
}else if(op1[0]=='-'&&op2[0]=='+'){
addegde(a,b);
addegde(b+n,a+n);
}
}
bool ans=two_sat();
printf("%d\n",ans==true?1:0);
return 0;
}
int main()
{
while(scanf("%d%d",&n,&m)==2){
deal();
}
return 0;
}