//二分图染色法(依次染色)
//首先要确定所有人都被限定过,否则直接输出no,
//再将已经确定好good和bad的人进行染色,判断有没有发生冲突,冲突输出no,
//最后将剩下还没染色的人依次染色(由于再前一次染色并未被染色,说明对剩下的染色不会和已染的人发生冲突,只要判断对剩下的人染色时是否冲突即可),冲突输出no,到最后还未输出no则输出yes
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10, M = 1e4 + 10;
int e[M], ne[M], h[N], vis[N] ,idx;
int cl[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;//链式前向星加边
}
void reset(int m,int n){
for(int i=1;i<=m;i++){
e[i]=0;
ne[i]=0;
}
for(int i=1;i<=n;i++){
cl[i]=0;
vis[i]=0;
h[i]=0;
}
idx=1;//从1开始,防止dfs时循环判断条件i是否未零出错(de了半小时这个)
}//初始化数据
bool dfs(int n,int clo){
cl[n]=clo;
for(int i=h[n];i;i=ne[i]){
int to=e[i];
if(cl[n] == cl[to]) return 0;//染色冲突
if(!cl[to]){
if(!dfs(to,3-clo)) return 0;//未染色则dfs继续染色,直到相关点全部被染色
}
}
return 1;
}
void solve(int n){
for(int i=1;i<=n;i++){//如果有点没有限制条件,则无法确定直接输出no
if(vis[i]==0){
printf("NO\n");
return;
}
}
for(int i=1;i<=n;i++){//对颜色确定的点染色
if(cl[i]){
if(!dfs(i,cl[i])){//冲突输出no
printf("NO\n");
return;
}
}
}
for(int i=1;i<=n;i++){//对第一轮染色未被染色的点染色
if(!cl[i]){
if(!dfs(i,1)){//冲突输出no(此处染1,2均可,因为此时尚未染色的点和前面的点相互独立,只要判断剩下的点是否构成二分图即可)
printf("NO\n");
return;
}
}
}
printf("YES\n");
return;
}
int main(){
int m,n,x,y;
while(~scanf("%d%d%d%d",&n,&m,&x,&y)){
reset(m,n);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
vis[a]=1;
vis[b]=1;
}
for(int i=1;i<=x;i++){
int xn;
scanf("%d",&xn);
vis[xn]=1;
cl[xn]=1;
}
for(int i=1;i<=y;i++){
int yn;
scanf("%d",&yn);
vis[yn]=1;
cl[yn]=2;
}//输入
solve(n);
}
}
10-17
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交