暂无链接
游戏攻略
GISPZJZ 在玩一款火爆的游戏,游戏中有nnn个技能点,编号分别为1,2,…,n1,2,…,n1,2,…,n。有些技能 点可以直接学习,还有一些技能点需要你已经学习某些技能点,才能够学习。一开始 GISPZJZ 没有学习任何技能点,现在 GISPZJZ 想知道,他最多能够学习技能池里的多少个技能。
输入:
第一行一个正整数nnn。
接下来 nnn 行,第i+1i+1i+1 行先输入一个整数 sis_isi,接下来输入sis_isi 个正整数 as1,as2,…,asia_{s_1},a_{s_2},…,a_{s_i}as1,as2,…,asi。 表示学习第 iii 个技能,需要先学习的技能点。si=0s_i=0si=0 表示学习iii 技能没有任何前置条件。
输出:
一行一个整数 ,表示 GISPZJZ 能学习的最大技能数。
样例输入:
4
0
1 1
2 1 4
2 1 3
样例输出:
2
样例说明:
GISPZJZ 可以按顺序学习技能 1,技能 2,然后无法获得其他的技能点。
数据范围:
对于 10%10\%10%的数据,1≤n≤10,1≤s1+s2+…+sn≤101≤n≤10,1≤s_1+s_2+…+s_n≤101≤n≤10,1≤s1+s2+…+sn≤10。
对于 40%40\%40%的数据,1≤n≤500,1≤s1+s2+…+sn≤5001≤n≤500,1≤s_1+s_2+…+s_n≤5001≤n≤500,1≤s1+s2+…+sn≤500。
对于额外 10%10\%10%的数据,满足对任意 1≤i≤n,si≥11≤i≤n,s_i\ge 11≤i≤n,si≥1。
对于额外 20%20\%20%的数据,满足对任意 1≤i≤n,si≤11≤i≤n,s_i≤11≤i≤n,si≤1。
对于 100%100\%100%的数据,1≤n≤100000,1≤s1+s2+…+sn≤1000001≤n≤100000,1≤s_1+s_2+…+s_n≤1000001≤n≤100000,1≤s1+s2+…+sn≤100000。
题解
技能加点相当于一个图,每次将入度为000的点删去,更新其他点的入度,答案+1+1+1,类似于拓扑排序。
不知道为什么考场上脑子抽了写一个用优先队列的O(nlogn)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();
2044

被折叠的 条评论
为什么被折叠?



