题目大意:
Problem Description
科学家小沃沃在研究病毒传播的规律,从而控制疫情。
有 nn 个人,编号分别为 1,2,…,n1,2,…,n。我们用荧光粉代替病毒,编号为 1 的人,在第 0 时刻涂上了荧光粉,剩下的人在第 0 时刻没有涂。
对于第 ii 个人,我们知道这个人在哪些时刻出现在了哪些地方。
如果时刻 tt,某个人和身体上有荧光粉的人,出现在了同一地点,那么从时刻 tt 以后,这个人也会沾上荧光粉。
从小到大输出实验结束后身体上有荧光粉的人的编号。
Input
第一行一个整数 T(1 \leq T \leq 20)T(1≤T≤20) 表示 TT 组数据。
对于每组数据,第一行一个整数 n (1 \leq n \leq 20000)n(1≤n≤20000) 表示 nn 个人。
对于第 ii 个人,第一行输入一个整数 len[i](1 \leq len[i] \leq 100 )leni 表示这个人的活动轨迹。
接下来 len[i]len[i] 行,每行输入两个整数 t, p(1 \leq t \leq 100, 1 \leq p \leq 10)t,p(1≤t≤100,1≤p≤10) 表示这个人 tt 时刻出现在了 pp 位置,保证 tt 按严格递增的顺序给出。
除了这 len[i]len[i] 个时刻,这个人都呆在家里,或者换句话说,他/她不在任何位置。 保证 len[1] + len[2] + … + len[n] \leq 200000len[1]+len[2]+…+len[n]≤200000。
Output
对于每组数据输出一行,表示所有患者的编号。按编号从小到大输出。
Sample Input
2
4
2
1 1
2 2
3
2 2
3 3
4 4
1
4 4
1
2 1
3
3
1 1
3 1
6 1
3
4 1
5 1
6 1
1
5 1
Sample Output
Copy
1 2 3
1 2
样例解释
Case 1:
第 2 时刻,位置 2,1 与 2 相遇,2 沾上了。
第 4 时刻,位置 4,2 与 3 相遇,3 沾上了。
这个问题就是问你最后有多少人感染,并且按编号从小到大输出。解决这个问题主要是判断在同一时间同一地点出现过什么样得人。首先我们要开一个dis数组来表明这个人是否感染,然后再来找和他出现在同一时间同一地点的人。我们先将所有的时间地点记录下来,并且记录下它相应的编号,然后我们排序(先按时间,再按地点,最后按编号)。因为一个人的感染是按她感染后的时间,然后就进行找就可以了
代码:
#include <queue>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5+9;
struct node
{
ll id,t,p;
}a[maxn];
ll dis[maxn];
bool cmp(node x,node y)
{
if(x.t!=y.t)
return x.t<y.t;
if(x.p!=y.p)
return x.p<y.p;
return x.id<y.id;
}
int main()
{
ll t,n,m,i,j;
scanf("%lld",&t);
while(t--)
{
memset(dis,0,sizeof(dis));
scanf("%lld",&n);
ll ant=0;
for(i=1;i<=n;i++)
{
scanf("%lld ",&m);
for(j=0;j<m;j++)
{
scanf("%lld %lld",&a[ant].t,&a[ant].p);
a[ant].id=i;
ant++;
}
}
sort(a,a+ant,cmp);
dis[1]=1;
for(i=1;i<ant;i++)
{
if(dis[a[i].id]==1||dis[a[i-1].id]==1)
{
if(a[i].t==a[i-1].t&&a[i].p==a[i-1].p)
{
dis[a[i].id]=1;
dis[a[i-1].id]=1;
j=i;
while(a[j].t==a[j-1].t&&a[j].p==a[j-1].p)
{
dis[a[j-1].id]=1;
dis[a[j].id]=1;
j--;
}
}
}
}
printf("1");
for(i=2;i<=n;i++)
{
if(dis[i])
printf(" %lld",i);
}
printf("\n");
}
}