HDU

来源:互联网 发布:知轩藏书下载 编辑:程序博客网 时间:2024/06/07 22:42

题目链接:HDU - 5971 Wrestling Match

Time Limit Memory Limit 2000/1000 MS (Java/Others) 65536/65536 K (Java/Others)

Problem Description

Nowadays, at least one wrestling match is held every year in our country. There are a lot of people in the game is “good player”,
the rest is “bad player”. Now, Xiao Ming is referee of the wrestling match and he has a list of the matches in his hand. At the same time, he knows some people are good players,some are bad players. He believes that every game is a battle between the good and the bad player. Now he wants to know whether all the people can be divided into “good player” and “bad player”.

Input

contains multiple sets of data.For each set of data,there are four numbers in the first line:N (1 ≤ N≤ 1000)、M(1 ≤M ≤ 10000)、X,Y(X+Y≤N ),in order to show the number of players(numbered 1toN ),the number of matches,the number of known “good players” and the number of known “bad players”.In the next M lines,Each line has two numbersa, b(a≠b) ,said there is a game between a and b .The next line has X different numbers.Each number is known as a “good player” number.The last line contains Y different numbers.Each number represents a known “bad player” number.Data guarantees there will not be a player number is a good player and also a bad player.

Output

If all the people can be divided into “good players” and “bad players”, output “YES”, otherwise output “NO”.

Sample Input

5 4 0 0
1 3
1 4
3 5
4 5
5 4 1 0
1 3
1 4
3 5
4 5
2

Sample Output

NO
YES


题意

有n个人,m场摔跤比赛,其中已确定x个好的选手,y个差的选手。
问能否将每个人划分成好的选手或差的选手。

自己做的AC了,但是发现有错。
搜答案,知道了这是个二分图的题,发现有的答案能AC,但是明显是错的。

二分图简介

简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。
准确地说:把一个图的顶点划分为两个不相交集 X 和 Y ,使得每一条边都分别连接X 、 Y 中的顶点。如果存在这样的划分,则此图为一个二分图。
二分图的一个等价定义是:不含有「奇数条边的环」的图。
图 1 是一个二分图。为了清晰,我们以后都把它画成图 2 的形式。
这里写图片描述

在图二中,我们可以把1,2,3,4看成X组,5,6,7,8看成Y组,
X组中的点只能连Y中的点。
奇数条边的环相当于一个点和X,Y组都有连线,这样就不能把他分在X组,也不能分在Y组,就不是二分图。

在本题中:如图二,我们可以假设1是好选手,和他比赛的5,7的就都是差的选手,2和差的5比赛,2是好选手。如果1和2之间还有比赛,就不符合题意,因为1,2都是好选手,这种情况也就是奇数边的环。

思路

dfs染色先从已经确定的人开始染色与其相关的人,矛盾就 NO
然后对于不确定的人,枚举染色,如果矛盾就是 NO
如果最后还存在不确定的,那么就是 NO
否则就是 YES

正确的AC代码

#include<bits/stdc++.h>using namespace std;const int MAX_N=1005;int n,color[MAX_N];vector<int> G[MAX_N];bool dfs(int v,int c){    color[v]=c;    for(unsigned i=0;i<G[v].size();++i)    {        if(color[G[v][i]]==c)            return false;        if(color[G[v][i]]==0&&!dfs(G[v][i],-c))            return false;    }    return true;}void solve(){    for(int i=1;i<=n;++i)        if(color[i]==-1)        {            cout<<"NO\n";            return;        }    for(int i=1;i<=n;++i)    {        if(color[i]==2&& !dfs(i,2))        {            cout<<"NO\n";            return;        }        if(color[i]==-2&& !dfs(i,-2))        {            cout<<"NO\n";            return;        }    }    for(int i=1;i<=n;++i)        if(color[i]==0)        {            if(!dfs(i,2))            {                cout<<"NO\n";                return;            }        }    cout<<"YES\n";}int main(){    ios::sync_with_stdio(false);    int m,x,y;    while(cin>>n>>m>>x>>y)    {        int a,b;        for(int i=1;i<=n;++i)//清空数据            G[i].clear();        memset(color,-1,sizeof(color));        for(int i=1;i<=m;++i)        {            cin>>a>>b;            color[a]=0;            color[b]=0;            G[a].push_back(b);            G[b].push_back(a);        }        for(int i=1;i<=x;++i)        {            cin>>a;            color[a]=2;        }        for(int i=1;i<=y;++i)        {            cin>>b;            color[b]=-2;        }        solve();    }    return 0;}
0 0
原创粉丝点击