zl程序教程

您现在的位置是:首页 >  其他

当前栏目

[2018.11.03 T1] 游戏攻略

游戏 攻略 03 T1
2023-09-27 14:28:32 时间

暂无链接

游戏攻略

GISPZJZ 在玩一款火爆的游戏,游戏中有 n n n个技能点,编号分别为 1 , 2 , … , n 1,2,…,n 1,2,,n。有些技能 点可以直接学习,还有一些技能点需要你已经学习某些技能点,才能够学习。一开始 GISPZJZ 没有学习任何技能点,现在 GISPZJZ 想知道,他最多能够学习技能池里的多少个技能。

输入:

第一行一个正整数 n n n​。

接下来 n n n 行,第 i + 1 i+1 i+1 行先输入一个整数 s i s_i si,接下来输入 s i s_i si 个正整数 a s 1 , a s 2 , … , a s i a_{s_1},a_{s_2},…,a_{s_i} as1,as2,,asi。 表示学习第 i i i 个技能,需要先学习的技能点。 s i = 0 s_i=0 si=0 表示学习 i i i 技能没有任何前置条件。

输出:

一行一个整数 ,表示 GISPZJZ 能学习的最大技能数。

样例输入:

4
0
1 1
2 1 4
2 1 3

样例输出:

2

样例说明:

GISPZJZ 可以按顺序学习技能 1,技能 2,然后无法获得其他的技能点。

数据范围:

对于 10 % 10\% 10%的数据, 1 ≤ n ≤ 10 , 1 ≤ s 1 + s 2 + … + s n ≤ 10 1≤n≤10,1≤s_1+s_2+…+s_n≤10 1n101s1+s2++sn10

对于 40 % 40\% 40%的数据, 1 ≤ n ≤ 500 , 1 ≤ s 1 + s 2 + … + s n ≤ 500 1≤n≤500,1≤s_1+s_2+…+s_n≤500 1n5001s1+s2++sn500

对于额外 10 % 10\% 10%的数据,满足对任意 1 ≤ i ≤ n , s i ≥ 1 1≤i≤n,s_i\ge 1 1insi1

对于额外 20 % 20\% 20%的数据,满足对任意 1 ≤ i ≤ n , s i ≤ 1 1≤i≤n,s_i≤1 1insi1

对于 100 % 100\% 100%的数据, 1 ≤ n ≤ 100000 , 1 ≤ s 1 + s 2 + … + s n ≤ 100000 1≤n≤100000,1≤s_1+s_2+…+s_n≤100000 1n1000001s1+s2++sn100000

题解

技能加点相当于一个图,每次将入度为 0 0 0的点删去,更新其他点的入度,答案 + 1 +1 +1,类似于拓扑排序。

不知道为什么考场上脑子抽了写一个用优先队列的 O ( n log ⁡ n ) O(n\log n) O(nlogn)算法。。。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int id,du;};
bool operator<(sd a,sd b){return a.du>b.du;}
int ru[M],n,ans;
bool vis[M];
vector<int>mmp[M];
priority_queue<sd>dui;
void in()
{
	scanf("%d",&n);
	for(int i=1,j,a,b;i<=n;dui.push((sd){i,ru[i]}),++i)
	for(scanf("%d",&a),ru[i]=a,j=1;j<=a;++j)
	scanf("%d",&b),mmp[b].push_back(i);
}
void ac()
{
	for(sd f;!dui.empty();)
	{
		f=dui.top();dui.pop();
		if(vis[f.id])continue;
		if(f.du)break;
		vis[f.id]=1,++ans;
		for(int i=mmp[f.id].size()-1;i>=0;--i)
		dui.push((sd){mmp[f.id][i],--ru[mmp[f.id][i]]});
	}
	printf("%d",ans);
}
int main(){in(),ac();