永不言弃 (topsort+优先队列)
Posted CCSU_Cola
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了永不言弃 (topsort+优先队列)相关的知识,希望对你有一定的参考价值。
题意:
小沙最喜欢打怪升级了,今天他玩了一个游戏,需要从初始关卡开始,击败n个关卡才能通关整个游戏,对于每个关卡都会有两种通过方式。
小沙初始的属性值为s,当游戏角色的属性大于关卡最高上限时,可以强行通过该关卡,又或者拥有通过该关卡的必过道具(并不是消耗品)。每个关卡通过后可能会开启一个或多个后置关卡,但每个关卡开启也需要若干个前置关卡,只有前置关卡全部通过后,才能开启该关卡。特别注意,除了一号关卡,如果一个关卡没有任何前置关卡,那么这个关卡则永远无法开启。
每个关卡仅能游玩一次,且每个关卡通过都会增强小沙角色的属性,也会给予一个必过道具。目前小沙正在一号关卡,请问小沙能否将这个游戏打通。
思路:首先每个点需要前驱节点都已经被遍历,刚好满足拓扑排序的顺序,但是由于每个点的后继节点比较多,有可能先遍历到的点不能通过,但是由于后面拿到卡片或者增加了属性,导致之前不能过的点,现在能通过,要将每个有卡片的点的关卡最高上限改为0,然后压入优先队列里,如果某一次优先队列里最小的关卡都不能通过,说明没有路可以走了,如果能遍历结束,说明能够走完。(之前想到的思路是修改掉已经压入队列的点的权值,但是后面发现修改复杂度太高,后面才知道不需要修改,只需要重新压入一个修改过的点即可,然后每个出来的点判断一下之前是否已经出来过就可以去重了)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int val[100010],b[100010];
int gs[100010],gb[100010];
int h[50010];
struct tt{
int x,to;
};
tt e[500010];
int d[50010];
int idx=0;
priority_queue<pair<ll, ll>, vector<pair<ll, ll>>,greater<pair<ll,ll> > >w;
void add(int a,int b){
e[idx].x=b,e[idx].to=h[a],h[a]=idx++;
}
int q[50010];
int n,s;
int vis[100010],vvis[100010];
ll sum=0;
vector<int>ans[50100];
bool topsort(){
sum=s;
w.push(make_pair(val[1],1));
while(!w.empty()){
pair<ll,ll>node=w.top();
w.pop();
if(node.first>=sum){
printf("No\\n");
return 0;
}
if(vis[node.second])continue;
vis[node.second]=1;
if(!vvis[b[node.second]]){
vvis[b[node.second]]=1;
for(int i=0;i<ans[b[node.second]].size();i++){
pair<ll,ll> ff;
ff.first=0;
ff.second=ans[b[node.second]][i];
//cout<<ff.second<<endl;
if(!d[ans[b[node.second]][i]])w.push(ff);
}
}
for(int i=h[node.second];i!=-1;i=e[i].to){
int j=e[i].to;
d[j]--;
if(!d[j]){
pair<ll,ll> ff;
ff.first=val[j];
ff.second=j;
w.push(ff);
}
}
}
return true;
}
int main(){
memset(h,-1,sizeof h);
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++){
scanf("%d%d",&val[i],&b[i]);
ans[b[i]].push_back(i);
}
for(int i=1;i<=n;i++){
scanf("%d%d",&gs[i],&gb[i]);
}
int k,x;
for(int i=1;i<=n;i++){
scanf("%d",&k);
for(int j=1;j<=k;j++){
scanf("%d",&x);
add(i,x);
d[x]++;
}
}
int flag=true;
for(int i=2;i<=n;i++){
if(!d[i]){
flag=false;
}
}
if(d[1]) flag=false;
if(!flag)printf("No\\n");
else{
if(topsort())printf("Yes\\n");
}
}
以上是关于永不言弃 (topsort+优先队列)的主要内容,如果未能解决你的问题,请参考以下文章