题目描述
本场比赛有 n名出题人,m 名选手。
出题人从 1 至 n 依次标号,选手从 1 至 mm依次标号。
比赛结束后选手的最终排名为 11至 m 中其一,且互不相同。
报名结束后,第 ii位出题人看了看报名列表,对其他出题人说:我觉得只有这 k_iki 位选手有可能最终排名第一,他们分别是 a_{i,1},a_{i,2},\dots,a_{i,k_i}ai,1,ai,2,…,ai,ki。其他人不可能最终排名第一。
你面前屏幕上的这道题的出题人通过时空隧道,预先得知了谁是最终排名第一的选手。
出题人把这n位出题人的预测都告诉了你,还告诉你恰好只有 pp个出题人的预测是正确的。
请你求出哪些选手可能最终获得第一名,并以从小到大的顺序依次输出这些选手的编号。
输入格式
从标准输入中读取数据。
第一行,三个正整数 n,m,p,,表示出题人数,选手数,与正确预测数。
接下来 nn 行,每行第一个非负整数 k_i 表示第 ii 位出题人预测可能最终排名第一的选手位数;接下来 k_i个正整数 a_{i,1},a_{i,2},\dots,a_{i,k_i}ai,1,ai,2,…,ai,ki,表示这位出题人预测可能最终排名第一的选手编号。
输出格式
输出数据至标准输出中。
第一行,输出一个非负整数,表示可能最终获得第一名的选手个数。
第二行,以从小到大的顺序依次输出这些选手的编号。
4 3 2 2 2 3 1 1 3 1 2 3 2 1 3
1 2
结果求解
本题的实质是判断p位预测人预测某位选手可能会获得第一。
错误代码:错误原因是因为数组开的太大,开太小子任务测试点会无法通过测试
#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
int a[10010][10010]={0};
int b[100010];
int main()
{
cin>>n>>m>>p;
long long x,y;
for(int i=1;i<=n;i++)
{
cin>>x;
for(int j=1;j<=x;j++)
{
cin>>y;
a[i][y]=1;
}
}
int count=0;
for(int i=1;i<=m;i++)
{
int num=0;
for(int j=1;j<=n;j++)
{
if(a[j][i]==1)
{
num++;
}
}
if(num==p)
{
b[i]=1;
count++;
}
}
cout<<count<<endl;
for(int i=1;i<=m;i++)
{
if(b[i]==1)
{
cout<<i<<endl;
}
}
//会出现开大数组导致溢出情况,所以需要开单个数组来进行记录
return 0;
}
改进方法:
开单个数组记录,因为题中其实与第几位出题人预测无关
#include <bits/stdc++.h>
using namespace std;
int n,m;
int a[1000001];//用来记录预测是第一名的个数
int b[1000001];
int x;
int y;
int p;
int main(){
cin>>n>>m>>p;
for(int i=1; i<=n; i++){
cin>>x;//x代表预测第一名的总数
for(int j=1; j<=x; j++){
cin>>y;//预测第一名是第几位
a[y]++;//计录标号为x的人被预测为第一名的次数
}
}
int ans=0;
for(int i=1; i<=m; i++){
if(a[i]==p){
ans++;
}
}
cout<<ans<<endl;
for(int i=1; i<=m;i++){//输出编号
if(a[i]==p){
cout<<i<<" ";
}
}
return 0;
}