Problem Description
有n對夫妻被邀請參加一個聚會,因為場地的問題,每對夫妻中只有1人可以列席。在2n 個人中,某些人之間有著很大的矛盾(當然夫妻之間是沒有矛盾的),有矛盾的2個人是不會同時出現在聚會上的。有沒有可能會有n 個人同時列席?
Input
n: 表示有n對夫妻被邀請 (n<= 1000)
m: 表示有m 對矛盾關系 ( m < (n - 1) * (n -1))
在接下來的m行中,每行會有4個數字,分別是 A1,A2,C1,C2
A1,A2分別表示是夫妻的編號
C1,C2 表示是妻子還是丈夫 ,0表示妻子 ,1是丈夫
夫妻編號從 0 到 n -1
Output
如果存在一種情況 則輸出YES
否則輸出 NO
Sample Input
2
1
0 1 1 1
Sample Output
YES
Source
2009 Multi-University Training Contest 16 - Host by NIT
Recommend
lcy
由於題目問題。知道n對夫妻要上N個人。也就是每對夫妻出一個人。
可以這麼說。給出一條矛盾關系
如果是 i,j,0,0 ,可以連有向邊 i0->j1,j0->i1 若出來i0,則必須出來j1.類推
如果是 i,j,0,1 , 可以連有向邊 i0->j0,j1->i1
如果是 i,j,1,0 , 可以連有向邊 i1->j1,j0->i0
如果是 i,j,1,1 , 可以連有向邊 i1->j0,j1->i0
如此就建好了一個所有有約束關系的有向圖了,由於只是一個判定性問題,只需在這樣建立的有向圖上運行一次強連通算法,最後再判定所有的i0,j0是否存在於一個強連通分量即可。
/*
* @author ipqhjjybj
* @date 20130702
*
*/
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <utility>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define inf 0x3f3f3f3f
#define MAXN 2005
#define clr(x,k) memset((x),(k),sizeof(x))
#define clrn(x,k) memset((x),(k),(n+1)*sizeof(int))
#define cpy(x,k) memcpy((x),(k),sizeof(x))
#define Base 10000
typedef vector<int> vi;
typedef stack<int> si;
typedef vector<string> vs;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define rep(i,n) for(int i = 0;i < n;++i)
#define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
vector<int> vec[MAXN];
int n,m;
int id[MAXN],pre[MAXN],low[MAXN],s[MAXN],stop,cnt,scnt;
void init(){
int u,v;
for(int i = 0;i < n+n;i++) vec[i].clear();
for(int i = 0,a,b,c,d;i < m;i++){
scanf("%d %d %d %d",&a,&b,&c,&d);
u = (a<<1) + c ; v = (b<<1) + d;
vec[u].push_back(v^1);
vec[v].push_back(u^1);
}
stop=cnt=scnt=0;
clr(pre,-1);
clr(id,0);
}
void Tarjan(int v,int n){
int t,minc=low[v]=pre[v]=cnt++;
vector<int>::iterator pv;
s[stop++]=v;
for(pv=vec[v].begin();pv!=vec[v].end();++pv){
if(-1==pre[*pv]) Tarjan(*pv,n);
if(low[*pv] < minc) minc=low[*pv];
}
if(minc<low[v]){
low[v]=minc;return;
}do{
id[t=s[--stop]]=scnt;low[t]=n;
}while(t!=v);
++scnt;
}
int main(){
// freopen("3062.in","r",stdin);
int i;
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
init();
for(i = 0;i < n+n;i++)
if(-1==pre[i])
Tarjan(i,n+n);
//以下進行判斷
bool flag = true;
for(i=0;i<n;i++)
if(id[i<<1]==id[(i<<1)^1]){
flag=false;
break;
}
if(flag)
printf("YES\n");
else printf("NO\n");
}
return 0;
}
/*
* @author ipqhjjybj
* @date 20130702
*
*/
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <utility>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
using namespace std;
#define inf 0x3f3f3f3f
#define MAXN 2005
#define clr(x,k) memset((x),(k),sizeof(x))
#define clrn(x,k) memset((x),(k),(n+1)*sizeof(int))
#define cpy(x,k) memcpy((x),(k),sizeof(x))
#define Base 10000
typedef vector<int> vi;
typedef stack<int> si;
typedef vector<string> vs;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define rep(i,n) for(int i = 0;i < n;++i)
#define foreach(it,c) for(vi::iterator it = (c).begin();it != (c).end();++it)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
vector<int> vec[MAXN];
int n,m;
int id[MAXN],pre[MAXN],low[MAXN],s[MAXN],stop,cnt,scnt;
void init(){
int u,v;
for(int i = 0;i < n+n;i++) vec[i].clear();
for(int i = 0,a,b,c,d;i < m;i++){
scanf("%d %d %d %d",&a,&b,&c,&d);
u = (a<<1) + c ; v = (b<<1) + d;
vec[u].push_back(v^1);
vec[v].push_back(u^1);
}
stop=cnt=scnt=0;
clr(pre,-1);
clr(id,0);
}
void Tarjan(int v,int n){
int t,minc=low[v]=pre[v]=cnt++;
vector<int>::iterator pv;
s[stop++]=v;
for(pv=vec[v].begin();pv!=vec[v].end();++pv){
if(-1==pre[*pv]) Tarjan(*pv,n);
if(low[*pv] < minc) minc=low[*pv];
}
if(minc<low[v]){
low[v]=minc;return;
}do{
id[t=s[--stop]]=scnt;low[t]=n;
}while(t!=v);
++scnt;
}
int main(){
// freopen("3062.in","r",stdin);
int i;
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
init();
for(i = 0;i < n+n;i++)
if(-1==pre[i])
Tarjan(i,n+n);
//以下進行判斷
bool flag = true;
for(i=0;i<n;i++)
if(id[i<<1]==id[(i<<1)^1]){
flag=false;
break;
}
if(flag)
printf("YES\n");
else printf("NO\n");
}
return 0;
}