版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ACMER_2333/article/details/78483891
hdu-5971 二分图的判断
题意:给出若干组参赛者的信息,每组中都有一个goog player和bad player,再给出确定为good player和bad player的序号,问这些参赛者是否可以分成good player和bad player两大类。
先从good player 和 bad player 开始深搜,搜完后从剩余人中深搜,在搜索过程中,如果遇到矛盾的情况直接输出NO,否则的话输出YES
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_V = 1010;
int V,E;
int col[1010];///用来记录每位参赛者的信息(0:好坏信息未知,1:good player ,-1:bad player)
vector<int> G[MAX_V];///邻接表来存参赛者之间的关系
int n,m,x,y;
int vis[1010];//记录每位参赛者在样例中的是否出现(0:未出现,1:出现)
bool dfs(int s,int c)
{
col[s]=c;
for(int i=0;i<G[s].size();i++)
{
if(col[G[s][i]]==col[s])
return false;
if(col[G[s][i]]==0&&!dfs(G[s][i],-c))//再次搜索时,要改变c的值,因为一对参赛者的好坏属性是不一样的
return false;
}
return true;
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&x,&y))
{
memset(col,0,sizeof(col));
memset(vis,0,sizeof(vis));
int a,b,sum=0;///sum是用来记录样例中出现的参加比赛的人数
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
if(!vis[a])
{
vis[a]=1;
sum++;
}
if(!vis[b])
{
vis[b]=1;
sum++;
}
}
int dis;
for(int i=1;i<=x;i++)
{
scanf("%d",&dis);
col[dis]=1;
if(!vis[dis])
{
vis[dis]=1;
sum++;
}
}
for(int i=1;i<=y;i++)
{
scanf("%d",&dis);
col[dis]=-1;
if(!vis[dis])
{
vis[dis]=1;
sum++;
}
}
if(sum!=n) /////sum!=n,导致某些参赛者的信息无法判断(究竟是好人还是坏人无法判断),直接输出NO
{
printf("NO\n");
continue;
}
int flog=0;
///////先从good player 开始深搜///////
for(int i=1;i<=n;i++)
{
if(col[i]==1)
{
if(!dfs(i,1))
{
flog=1;
break;
}
}
}
////从bad player 开始深搜////
for(int i=1;i<=n;i++)
{
if(col[i]==-1)
{
if(!dfs(i,-1))
{
flog=1;
break;
}
}
}
////从还未确定信息的参赛者深搜///
for(int i=1;i<=n;i++)
{
if(col[i]==0)
{
if(!dfs(i,1))
{
flog=1;
break;
}
}
}
// for(int i=1;i<=n;i++)
// cout<<col[i]<<endl;
if(flog)
printf("NO\n");
else
printf("YES\n");
for(int i=1;i<=n;i++)
G[i].clear();
}
return 0;
}