题目:http://acm.hdu.edu.cn/showproblem.php?pid=5971
校内比赛一共三个小时怼了一个半小时才做出来的题,题意一直理解的不算清晰。
题目大意:摔跤比赛,将运动员分为好运动员坏运动员两个阵营,给出人数,比赛场数及比赛安排,已知的好运动员和坏运动员,让你判断是否所有运动员都能分为好坏两个阵营。
思路:不能分为两阵营的情况分别有
(1)有运动员未参加比赛且不已知属于哪个阵营
(2)有运动员与两阵营的选手均为对手
(3)假定一名参加比赛但通过已知好坏运动员的关系无法确定属于哪个阵营的选手属于好运动员,再次遍历染色不发生(2)的矛盾
(4)存在经过以上判断假设仍无法确定属于那个阵营的运动员
代码:c++
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int player[1001][1001];
int cot[1001];
int belong[1001];
bool num[1001];
bool check(int N)
{
int i;
for(i=1; i<=N; i++)
{
if(belong[i]==0)
return false;
}
return true;
}
int main()
{
int i,j,k;
int N,M,X,Y,a,b,t;
while(scanf("%d%d%d%d", &N, &M, &X, &Y)!=EOF)
{
memset(player,0,sizeof(player));
memset(cot,0,sizeof(cot));
memset(belong,0,sizeof(belong));
memset(num,0,sizeof(num));
t = 1;
for(i=0; i<M; i++)
{
scanf("%d%d", &a, &b);
num[a] = true;
num[b] = true;
player[a][cot[a]] = b;
cot[a]++;
player[b][cot[b]] = a;
cot[b]++;
}
for(i=0; i<X; i++)
{
scanf("%d", &a);
num[a] = true;
belong[a] = 1;//goodplayer
for(j=0; j<cot[a]; j++)
{
belong[player[a][j]] = 2;
}
}
for(i=0; i<Y; i++)
{
scanf("%d", &b);
num[b] = true;
belong[b] = 2;//badplayer
for(j=0; j<cot[b]; j++)
{
belong[player[b][j]] = 1;
}
}
for(i=1; i<=N; i++)
{
if(belong[i]!=0)
{
if(belong[i]==1)
{
for(j=0; j<cot[i]; j++)
{
if(belong[player[i][j]]==1)
t = 0;
belong[player[i][j]] = 2;
}
}
else
{
for(j=0; j<cot[i]; j++)
{
if(belong[player[i][j]]==2)
t = 0;
belong[player[i][j]] = 1;
}
}
}
}
for(i=1; i<=N; i++)
{
if(belong[i]==0&&num[i]==true)
{
belong[i] = 1;
break;
}
}
for(i=1; i<=N; i++)
{
if(belong[i]!=0)
{
if(belong[i]==1)
{
for(j=0; j<cot[i]; j++)
{
if(belong[player[i][j]]==1)
t = 0;
belong[player[i][j]] = 2;
}
}
else
{
for(j=0; j<cot[i]; j++)
{
if(belong[player[i][j]]==2)
t = 0;
belong[player[i][j]] = 1;
}
}
}
}
if(t==1&&check(N))
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}