暂无链接
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 1≤n≤10,1≤s1+s2+…+sn≤10。
对于 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 1≤n≤500,1≤s1+s2+…+sn≤500。
对于额外 10 % 10\% 10%的数据,满足对任意 1 ≤ i ≤ n , s i ≥ 1 1≤i≤n,s_i\ge 1 1≤i≤n,si≥1。
对于额外 20 % 20\% 20%的数据,满足对任意 1 ≤ i ≤ n , s i ≤ 1 1≤i≤n,s_i≤1 1≤i≤n,si≤1。
对于 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 1≤n≤100000,1≤s1+s2+…+sn≤100000。
技能加点相当于一个图,每次将入度为 0 0 0的点删去,更新其他点的入度,答案 + 1 +1 +1,类似于拓扑排序。
不知道为什么考场上脑子抽了写一个用优先队列的 O ( n log n ) O(n\log n) O(nlogn)算法。。。
#include
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();