题型:图论
题意:
中文题,不解释
原题戳http://acm.hdu.edu.cn/showproblem.php?pid=3062
分析:
赤果果的2-SAT练习题,因为夫妻只能出席其中一人,正好构成A与~A
如果两个妻子有矛盾, A->~B
B->~A
如果一女一男有矛盾, A-> B
~B->~A
如果一男一女有矛盾, B-> A
~A->~B
如果两个丈夫有矛盾,~A-> B
~B-> A
代码:
#include
#include
#include
#include
#include
#include
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M = 2005;
class Twosat {
class Tarjan {
struct E {
int u,v,next;
} e[M*M];
int le,head[M],Index,Bcnt,num[M],belong[M],dfn[M],low[M];
bool instack[M];
stack s;
void tarjan(int u) {
dfn[u]=low[u]=++Index;
instack[u]=true;
s.push(u);
int v;
for(int i=head[u]; ~i; i=e[i].next) {
v=e[i].v;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
} else if(instack[v]) {
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]) {
Bcnt++;
do {
v=s.top();
s.pop();
instack[v]=false;
belong[v]=Bcnt;
num[Bcnt]++;
} while(u!=v);
}
}
public:
void init() {
le=Index=Bcnt=0;
mt(head,-1);
mt(num,0);
mt(dfn,0);
mt(low,0);
mt(instack,0);
while(!s.empty()) s.pop();
}
void add(int u,int v) {
e[le].u=u;
e[le].v=v;
e[le].next=head[u];
head[u]=le++;
}
void solve(int n) {
for(int i=1; i<=n; i++) {
if(!dfn[i]) {
tarjan(i);
}
}
}
int getbcnt() {
return Bcnt;
}
int getbelong(int id) {
return belong[id];
}
int getnum(int id) {
return num[id];
}
} T;
class Unitenode {
struct E {
int u,v,next;
} e[M*M];
int n,le,head[M],in[M];
bool mat[M][M];
queue q;
public:
void init(int x) {
n=x;
le=0;
mt(head,-1);
mt(in,0);
mt(mat,0);
for(int i=1; i<=n; i++) mat[i][i]=true;
}
void add(int u,int v) {
if(!mat[u][v]) {
in[v]++;
mat[u][v]=true;
e[le].u=u;
e[le].v=v;
e[le].next=head[u];
head[u]=le++;
}
}
void solve(int tp[]) {
while(!q.empty()) q.pop();
for(int i=1; i<=n; i++) {
if(!in[i]) {
q.push(i);
}
}
int ret=1;
while(!q.empty()) {
int u=q.front();
q.pop();
tp[ret++]=u;
for(int i=head[u]; ~i; i=e[i].next) {
int v=e[i].v;
in[v]--;
if(!in[v]) {
q.push(v);
}
}
}
}
} U;
void unite() {
U.init(T.getbcnt());
for(int i=1; i<=n; i++) {
for(int j=head[i]; ~j; j=e[j].next) {
U.add(T.getbelong(i),T.getbelong(e[j].v));
}
}
}
struct E {
int u,v,next;
} e[M*M];
int n,le,head[M],tp[M];
bool flag[M];
public:
void init(int x) {
n=x;
T.init();
le=0;
mt(head,-1);
}
void add(int u,int v) {
T.add(u,v);
e[le].u=u;
e[le].v=v;
e[le].next=head[u];
head[u]=le++;
}
bool solve() {
T.solve(n);
for(int i=1,z=n/2; i<=z; i++) {
if(T.getbelong(i)==T.getbelong(i+z))return false;
}
return true;
}
void output(bool ans[]) {
unite();
U.solve(tp);
mt(flag,0);
for(int i=T.getbcnt(); i>0; i--) {
for(int j=1,y; j<=n; j++) {
if(j>n/2)y=j-n/2;
else y=j;
if(!flag[y]&&T.getbelong(j)==tp[i]) {
flag[y]=true;
if(j>n/2) {
ans[j-n/2]=true;
} else {
ans[j]=false;
}
}
}
}
}
} gx;
int main() {
int n,m;
while(~scanf("%d",&n)){
gx.init(n*2);
scanf("%d",&m);
int a,b,C1,C2;
while(m--){
scanf("%d%d%d%d",&a,&b,&C1,&C2);
a++;
b++;
if(C1==0 && C2==0){
gx.add(a,b+n);
gx.add(b,a+n);
continue;
}
if(C1==0 && C2==1){
gx.add(a,b);
gx.add(b+n,a+n);
continue;
}
if(C1==1 && C2==0){
gx.add(b,a);
gx.add(a+n,b+n);
continue;
}
if(C1==1 && C2==1){
gx.add(a+n,b);
gx.add(b+n,a);
continue;
}
}
if(gx.solve()) puts("YES");
else puts("NO");
}
return 0;
}