• Kernel Knights (Gym


    题目链接

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    int a[200005];   //存放原始数据
    int vis[200005]; //标记选的对手
    int b[200005]; //答案序列
    queue<int>q; //把所有能够选的都存一次,接着遍历与它有关系的。
    int main()
    {
        int n,x;
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));  //初始化
        memset(b,0,sizeof(b));      
        //memset(a,0,sizeof(a));
        for(int i = 1; i <= 2*n; i ++)
        {
            scanf("%d",&a[i]);
            vis[a[i]]++;
        }
        for(int i = 1; i <= 2*n; i ++)  // 把能够选的放入到队列中,遍历与它相连的是否可以选上
        {
            if(vis[i] == 0)
                q.push(i);
        }
        while(!q.empty())
        {
            int x = q.front();
            q.pop();
            b[x] = 1;    // 表示可以选择放入到S中
            if(b[a[x]]==-1)   // 如果x被选上了,那么x所选的对手被处理过一次不能选,跳过就可以
                continue;    //因为不跳出,vis会再重复减一次,导致答案会增多或者减少一些
            b[a[x]] = -1;  
            vis[a[a[x]]] --;   // x选的对手y,y选的对手要减1,因为x被选进S中,y现在就相当于x的位置,y的选的对手就可以放进S中
            if(vis[a[a[x]]] == 0)  //当vis[z = a[a[x]]]为0,说明没有人挑战z,所以z要放进S中
                q.push(a[a[x]]);
        }
        for(int i=1; i<=2*n; i++)
        {
            if(i<=n&&b[i]>=0)  // 在第一房间(排)中,只要符合不与下面的在一个集合中就可以选择
                printf("%d ",i);
            else if(b[i]==1)
                printf("%d ",i);
        }
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    webgame模块划分
    VC的若干实用小技巧(一)
    反病毒技术:从亡羊补牢到免疫防御
    MySQL 备份和恢复
    企业网络安全整体解决方案
    大型银行核心网络的三层结构设计
    编写"优美"的SHELLCODE
    linux中apache访问控制配置文件。
    网站同步镜像制作!
    Linux远程桌面(vnc)
  • 原文地址:https://www.cnblogs.com/lcchy/p/10139505.html
Copyright © 2020-2023  润新知