c++ map set综合运用

题目地址:
http://www.nowcoder.com/practice/d311403b15b8495b81b622edaefd5b5a?tpId=49&tqId=29312&rp=3&ru=/ta/2016test&qru=/ta/2016test/question-ranking

题目描述

现在我们需要查出一些作弊的问答社区中的ID,作弊有两种:1.A回答了B的问题,同时B回答了A的问题。那么A和B都是作弊。2.作弊ID用户A和作弊ID用户B同时回答了C的问题,那么C也是作弊。已知每个用户的ID是一串数字,一个问题可能有多个人回答。

输入描述:
每组数据第一行为总问题数N(N小于等于200000),第二行开始每行一个问题,第一个数字为提问人ID,第二个数字为回答人数,后面则为所有回答人的ID。(ID均为0-1000000的整数)

输出描述:
第一行为作弊ID数量,第二行开始为从小到大的每行一个作弊ID。

输入例子:
3
1 1 2
2 1 1
3 2 1 2

输出例子:
3
1
2
3

相关解答:
http://www.nowcoder.com/questionTerminal/d311403b15b8495b81b622edaefd5b5a

ac代码

#include <cstdio>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <list>
#include <set>
#include <iterator>
#include <string>
#include <cstring>
#include <algorithm>

using namespace std;

const int INF = 0x7fffffff;
const int MIN = -INF - 1;


int main()
{
    //freopen("in.txt", "r", stdin);
    int n;

    while (scanf("%d", &n) != EOF)
    {
        map<int, set<int>> answer;
        vector<pair<int, int>> ab; //同时作弊的两个人
        set<int> rs;//保存最终的结果
        map<int, bool> isbad;// map 映射 某个id是否是作弊的人(作用:减少不必要的查找)

        int i,j,cnt,id,aid;
        for (i = 1; i <= n; i++)
        {
            scanf("%d%d", &id,&cnt);
            for (j = 0; j < cnt; j++)
            {
                scanf("%d", &aid);
                answer[id].insert(aid);
            }
            isbad[id] = false;
        }

        // 找作弊的A B
        map<int, set<int>>::iterator it = answer.begin();
        while (it != answer.end())
        {
            id = it->first;// 当前id

            set<int> aids = it->second;// 回答他问题的ids
            for (set<int>::iterator ait = aids.begin(); ait != aids.end(); ait++)
            {
                // 在回答他问题的ids中找到的当前id,则两个人都是作弊的
                if (id != *ait && !(isbad[id] && isbad[*ait]) && answer[*ait].find(id) != answer[*ait].end())
                {
                    ab.push_back(pair<int, int>(id, *ait));
                    rs.insert(id);
                    rs.insert(*ait);
                    isbad[id] = true;
                    isbad[*ait] = true;
                }
            }
            it++;
        }

        // 找作弊的C
        for (it = answer.begin(); it != answer.end(); it++)
        {
            id = it->first;// 当前id
            if (isbad[id] == false)
            {
                set<int> b = it->second;// 回答他问题的ids

                for (int i = 0; i < (int)ab.size(); i++)
                {
                    if (b.find(ab[i].first) != b.end() && b.find(ab[i].second) != b.end())
                        rs.insert(id);
                }
            }
        }

        // 打印结果
        int len = rs.size();

        printf("%d\n", len);
        if (len > 0){
            set<int>::iterator rsit = rs.begin();
            while (rsit != rs.end())
            {
                printf("%d\n", *rsit);
                rsit++;
            }
            /*set<int>::iterator rsit = rs.begin();
            printf("%d", *rsit);
            while (rsit != rs.end())
            {
                rsit++;
                if (rsit == rs.end())
                    break;
                printf(" %d", *rsit);
            }
            printf("\n");*/
        }

    }// while
    return (0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值