Kernel Knights (Gym - 101480K)

版权声明:本文为原创文章QWQ,如果有错误欢迎指正,转载请注明作者且附带网址 https://blog.csdn.net/Mercury_Lc/article/details/83017887

题目链接

#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("\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mercury_Lc/article/details/83017887
今日推荐