hdu 5971 Wrestling Match(队列)

Wrestling Match

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 19    Accepted Submission(s): 13



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场比赛,x个好人,y个坏人,对于每一场比赛,必有一个好人一个坏人,问是否能将n个人完全区分成好坏人。

思路:题意相当模糊,综合样例可以推测为不能有单独的人可以判成好坏人,那就很好做了,首先对已给的人对比赛进行推测区分出一些人,对无法区分的人,随便给个属性进行递推,唯一注意的就是对单独的人又没给出属性的情况下可以直接判断no.这题没什么好说的,水题罢了,若是wa了,必定是姿势不对,若是tle了,那是链式前向星的数组开小了。

代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1111;
struct node
{
    int u,v,next;
}edge[maxn*10*2];
struct E
{
    int w,id;
};
queue<E>q;
int head[maxn],cnt,vis[maxn];
void addedge(int u,int v)
{
    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u];head[u]=cnt++;
    edge[cnt].u=v;edge[cnt].v=u;edge[cnt].next=head[v];head[v]=cnt++;
}
int main()
{
    int T;
    int n,m,x,y;
    while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF)
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        memset(vis,-1,sizeof(vis));
        for(int i=0;i<m;i++)
        {
            int c,d;
            scanf("%d%d",&c,&d);
            addedge(c,d);
        }
        int xx;
        E a;
        int flag=0;
        while(!q.empty())
            q.pop();
        for(int i=0;i<x;i++)
        {
            scanf("%d",&xx);
            a.w=xx;
            a.id=0;
            vis[xx]=0;
            q.push(a);
        }
        for(int i=0;i<y;i++)
        {
            scanf("%d",&xx);
            vis[xx]=1;
            a.w=xx;
            a.id=1;
            q.push(a);
        }
        while(!q.empty())   //有给出的好坏人去区分比赛中的好坏人。
        {
            a=q.front();q.pop();
            int u=a.w,id=a.id;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(vis[v]==-1)
                {
                    vis[v]=!vis[u];
                    a.w=v;
                    a.id=vis[v];
                    q.push(a);
                }
                else if(vis[v]==vis[u])
                {
                    flag=1;
                    break;
                }
            }
        }
        if(!flag)
        for(int i=1;i<=n;i++)   //无法区分的好坏人,先判断是否是独立的个体,是则直接no,否则任意标记一个属性,进行再一轮推断。
        {
            if(vis[i]==-1)
            {
                if(flag)
                    break;
                if(head[i]==-1)
                {
                    flag=1;break;
                }
                vis[i]=0;
                a.w=i;
                a.id=0;
                q.push(a);
                while(!q.empty())
                {
                    a=q.front();q.pop();
                    int u=a.w,id=a.id;
                    for(int j=head[u];j!=-1;j=edge[j].next)
                    {
                        int v=edge[j].v;
                        if(vis[v]==-1)
                        {
                           vis[v]=!vis[u];
                           a.w=v;
                           a.id=vis[v];
                           q.push(a);
                        }
                        else if(vis[v]==vis[u])
                        {
                            flag=1;
                            break;
                        }
                     }
                }
            }
        }
        if(flag)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于HDU4546问题,还可以使用优先队列(Priority Queue)来解决。以下是使用优先队列的解法思路: 1. 首先,将数组a进行排序,以便后续处理。 2. 创建一个优先队列(最小堆),用于存储组合之和的候选值。 3. 初始化优先队列,将初始情况(即前0个数的组合之和)加入队列。 4. 开始从1到n遍历数组a的元素,对于每个元素a[i],将当前队列中的所有候选值取出,分别加上a[i],然后再将加和的结果作为新的候选值加入队列。 5. 重复步骤4直到遍历完所有元素。 6. 当队列的大小超过k时,将队列中的最小值弹出。 7. 最后,队列中的所有候选值之和即为前k小的组合之和。 以下是使用优先队列解决HDU4546问题的代码示例: ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); // 对数组a进行排序 priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆 pq.push(0); // 初始情况,前0个数的组合之和为0 for (int i = 0; i < n; i++) { long long num = pq.top(); // 取出当前队列中的最小值 pq.pop(); for (int j = i + 1; j <= n; j++) { pq.push(num + a[i]); // 将所有加和结果作为新的候选值加入队列 num += a[i]; } if (pq.size() > k) { pq.pop(); // 当队列大小超过k时,弹出最小值 } } long long sum = 0; while (!pq.empty()) { sum += pq.top(); // 求队列中所有候选值之和 pq.pop(); } cout << sum << endl; return 0; } ``` 使用优先队列的方法可以有效地找到前k小的组合之和,时间复杂度为O(nklog(k))。希望这个解法对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值