题意: 给出比赛的人的标号, 以及x个好人y个坏人。询问是否能判断他是一个好人或者坏人。 给出的关系是否不存在矛盾,并且没有既是好人又是坏人。
思路:
训练的时候这题理解错了,一直没过。 补题发现可以是多个连通块,就是说可以分为m堆,只要每个堆里不存在矛盾关系,且每个人都出现过就可以。
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=10005;
int go[maxn];
int vis[maxn];
int col[maxn];
int bad[maxn];
vector<int >vec[maxn];
int dfs(int u)
{
go[u]=1;
for(int i=0;i<vec[u].size();i++)
{
int v=vec[u][i];
if(!col[v] &&!bad[v] )
{
col[v]=!col[u];
if(!dfs(v))
return 0;
}
else
{
if(col[v]==col[u]) return 0;
}
}
return 1;
}
int main()
{
int n,m,x,y;
while(~scanf("%d%d%d%d",&n,&m,&x,&y))
{
for(int i=0;i<=n;i++)
vec[i].clear();
memset(bad,0,sizeof(bad));
memset(col,0,sizeof(col));
memset(go,0,sizeof(go));
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
vis[u]=vis[v]=1;
}
for(int i=1;i<=x;i++)
{
int u;
scanf("%d",&u);
vis[u]=col[u]=1;
}
for(int i=1;i<=y;i++)
{
int u;
scanf("%d",&u);
vis[u]=1;
bad[u]=1;
col[u]=0;
}
int cnt=0;
for(int i=1;i<=n;i++)
{
if(vis[i]) cnt++;
}
if(cnt<n){printf("NO\n");}
else
{
int yes=1;
for(int i=1;yes&&i<=n;i++)
{
if(go[i]) continue;
if(!dfs(i))
{
yes=0;
}
}
if(yes) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}