题目链接:Wrestling Match
题目大意:现在有N个人,M个对立的关系,有X个已知的好人,Y个已知的坏人,问能不能把所有的人都分成两堆某一堆里面,并且所有的限制条件都成立
题目思路:题意真傻逼,完全是猜题意,先把所有跟好人对立和坏人对立的关系全部扔出来,然后对还没有分到某一个阵营的枚举好人或者坏人两种情况,最后看有没有都对立或者还没有分到某一个阵营的人就好了
#include <map>
#include <set>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10005;
vector<int>vec[maxn];
int col[maxn],a[maxn],b[maxn];
bool vis[maxn],flag;
void dfs1(int x){
if(flag) return ;
for(int i = 0;i < vec[x].size();i++){
if(flag) return ;
if(col[vec[x][i]] == col[x]) {flag = true;return ;}
if(vis[vec[x][i]]) continue;
col[vec[x][i]] = (col[x]+1)%2;
vis[vec[x][i]] = true;
dfs1(vec[x][i]);
}
return ;
}
void dfs2(int x){
if(flag) return ;
for(int i = 0;i < vec[x].size();i++){
if(flag) return ;
if(col[vec[x][i]] == col[x]) {flag = true;return ;}
if(vis[vec[x][i]]) continue;
col[vec[x][i]] = (col[x]+1)%2;
vis[vec[x][i]] = true;
dfs2(vec[x][i]);
vis[vec[x][i]] = false;
}
return ;
}
int main(){
int n,m,x,y,u,v;
while(~scanf("%d%d%d%d",&n,&m,&x,&y)){
memset(col,-1,sizeof(col));
memset(vis,false,sizeof(vis));
flag = false;
for(int i = 0;i < maxn;i++) vec[i].clear();
while(m--){
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
for(int i = 0;i < x;i++){
scanf("%d",&a[i]);
col[a[i]] = 0;
vis[a[i]] = true;
dfs1(a[i]);
}
for(int i = 0;i < y;i++){
scanf("%d",&b[i]);
col[b[i]] = 1;
vis[b[i]] = true;
dfs1(b[i]);
}
if(flag) puts("NO");
else{
for(int i = 1;i <= n;i++){
if(flag) break;
if(col[i] == -1){
if(vec[i].size() != 0){
int cnt = 0;
col[i] = 1;
vis[i] = true;
dfs2(i);
vis[i] = false;
if(flag == false) cnt++,flag = true;
else continue;
col[i] = 2;
vis[i] = true;
dfs2(i);
vis[i] = false;
if(flag == false) cnt++;
if(cnt == 2) flag = true;
else flag = false;
}
}
}
for(int i = 1;i <= n;i++) if(col[i] == -1) flag = true;
if(!flag) puts("YES");
else puts("NO");
}
}
return 0;
}