HDU 5971 Wrestling Match 2016大连区域赛

Wrestling Match
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 8    Accepted Submission(s): 7


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
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



Source
2016ACM/ICPC亚洲区大连站-重现赛(感谢大连海事大学) 

题意比较不明…看了很久才搞出来 个人理解 就是:
n个人 给定m对关系:a,b不在一个集合中
已知x个人是好球员的集合中的人
y个人是坏球员
判断是否能分成2个集合
如果1是好球员 2是坏球员
其余的球员与1,2无关系 能分成2个集合 也算YES

并查集
x的球员设置在集合1 y的在集合0
先以x和y的球员作为起点 dfs确定球员关系
如果dfs中发现关系矛盾 ->NO
dfs完了 如果还有球员没确定集合 随便给一个没集合的球员设个集合
以该球员作为起点dfs
如果dfs完了 还有球员不能确定集合 ->NO
否则YES
坑爹的是!!!!!居然爆栈………
于是dfs改成队列…..就过了

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<time.h>
#include<math.h>
#include<list>
#include<cstring>
#include<fstream>
//#include<memory.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define INF 1000000007
#define pll pair<ll,ll>
#define pid pair<int,double>

const int N=1000+5;
const int M=10000+5;

int par[N];
inline int find(int x){
    return x==par[x]?x:par[x]=find(x);
}
vector<int>against[N];//against[i]保存与i不在一个集合的
vector<int>known;//保存x y的球员
bool visited[N];
bool dfs(int u){
    deque<int>de;
    de.push_back(u);
    while(!de.empty()){
        u=de[0];
        de.pop_front();
        if(visited[u])
            continue;
        visited[u]=true;
        for(int i=0;i<against[u].size();++i){
            int v=against[u][i];
            if(par[v]<0){
                par[v]=1^par[u];
                de.push_back(v);
            }
            else
                if(par[v]+par[u]!=1)//矛盾
                    return false;
        }
    }
    return true;
}

bool slove(int n){
    for(int i=0;i<known.size();++i){//以x y中的球员作起点 找一遍
        int u=known[i];
        if(visited[i]==true)
            continue;
        if(dfs(i)==false)
            return false;
    }
    for(int i=1;i<=n;++i){//有球员没有与任何球员有对立关系 又不是已知good bad 必定NO
        if(against[i].size()==0&&par[i]<0)
            return false;
    }
    int t=-1;//标记第一个没集合的球员
    for(int i=1;i<=n;++i){
        if(par[i]<0){
            t=i;
            par[t]=0;//设置成集合0
            break;
        }
    }
    if(t<0)//所有球员都有集合了
        return true;
    if(dfs(t)==false)
        return false;
    for(int i=1;i<=n;++i)//还有球员没集合
        if(par[i]<0)
            return false;
    return true;
}

int main()
{
    //freopen("/home/lu/文档/r.txt","r",stdin);
    //freopen("/home/lu/文档/w.txt","w",stdout);
    int n,m,x,y;
    while(~scanf("%d%d%d%d",&n,&m,&x,&y)){
        for(int i=1;i<=n;++i){
            par[i]=-1;
            visited[i]=false;
            against[i].clear();
        }
        known.clear();
        for(int i=0,u,v;i<m;++i){
            scanf("%d%d",&u,&v);
            against[u].push_back(v);
            against[v].push_back(u);
        }
        for(int i=0,u;i<x;++i){
            scanf("%d",&u);
            par[u]=1;//good=1
            known.push_back(u);
        }
        for(int i=0,u;i<y;++i){
            scanf("%d",&u);
            par[u]=0;//bad=0
            known.push_back(u);
        }
        puts(slove(n)?"YES":"NO");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值