题目大意:我们要攻略n个城堡,每个城堡有ai,bi,ci三个参数,我们到达城堡i时必须至少有ai个人才能攻略,不能攻略输出-1
到达一个城堡后能够加bi个人。同时我们允许放1个人在城堡i防守,这样我们能得到ci的分数。注意过了这个城堡就不能再选择之前的城堡进行防守。但是,这里有一些道路允许我们在城堡b到城堡a,其中b大于a。
解题思路:
很自然地,我们每次到达一个城堡都尽可能进行defend,每次到达一个城堡若人数不够,我们就反悔,把之前分数低的defend的城市取消。大概思路就是这样,我们只用维护一个优先队列就可以了。但是上面的思路有些问题,我们在人数不够的时候,优先pop出来的是分数低的,这样有个bug,比如可能到达某座城市i,它可能和一些城市连起来,这时候我们应该pop掉和i连接的城市。那怎么避免这种情况呢?这里有一个key hint。 一个城市若是后面可以defend,我们不要在前面就defend,这样总是最优的,比如i和j是连起来的,其中j>i,这时候我们假如不在i defend在jdefend的好处是:[i+1,j]区间人数多了一个,更有利于我们攻略城堡。而且这样可以避免我们之前所说的bug。
#include <bits/stdc++.h>
using namespace std;
typedef struct{
int a,b,c;
}cas;
vector<vector<int>> gra;
vector<int> flag;
vector<int> back;
int main(){
int n,m,k;cin>>n>>m>>k;
vector<cas> castle(n);
back.assign(n,0);
flag=vector<int> (n,0);
for(int i=0;i<n;i++){
cin>>castle[i].a>>castle[i].b>>castle[i].c;
}
gra=vector<vector<int>> (n);
for(int i=0;i<m;i++){
int a,b;cin>>a>>b;
a-=1;b-=1;
gra[a].emplace_back(b);
back[b]=max(back[b],a);
}
priority_queue<pair<int,int>,vector<pair<int,int>> ,greater<pair<int,int>>> pq;
int man=k;
for(int i=0;i<n;i++){
if(man<castle[i].a){
int dif=castle[i].a-man;
if((int)pq.size()<dif){
cout<<-1<<endl;
exit(0);
}else{
while(man<castle[i].a){
pair<int,int> ii= pq.top();
flag[ii.second]=0;
pq.pop();
man++;
}
}
}
man+=castle[i].b;
if(man){
priority_queue<pair<int,int> ,vector<pair<int,int>> , less<pair<int,int>> > tmp;
if(!back[i])
tmp.push(make_pair(castle[i].c,i));
for(int ii=0;ii<(int)gra[i].size();ii++){
int nx=gra[i][ii];
if(back[nx]!=i)continue;
if(!flag[nx]){
tmp.push(make_pair(castle[nx].c,nx));
}
}
while(tmp.size()>0 && man>0){
pair<int,int> ii=tmp.top();
tmp.pop();
flag[ii.second]=1;
pq.push(make_pair(ii.first,ii.second));
man-=1;
}
}
}
int ans=0;
while(pq.size()){
int no=pq.top().first;
pq.pop();
ans+=no;
}
cout<<ans<<endl;
return 0;
}
来源:CSDN
作者:FrostMonarch
链接:https://blog.csdn.net/FrostMonarch/article/details/103605394