补题啦啦啦

这里有 n 座城市,编号 1 ~ nn 座城市之间由 m双向道路相连,保证任意两所城市可相互到达。

学校位于第 k 座城市。临近寒假,来自各个城市的同学们都在准备回家过年,但因为特殊原因,现在所有城市都被封锁起来了(第 0 天)。

归乡心切的 Cofe_Milk 得到最新消息,从明天(第 1 天)开始,每天都将有一座城市解封。对于需要回到这座城市的同学,若想到达这座城市,则从学校出发,到达这座城市的路径上的所有城市都应是解封状态(当然,路径也包括学校所在城市与目的地城市)。我们称来自这所城市的同学的回家日便是他们可以回家的最小日期。

特别的:家在第 k 所城市的同学也需要第 k 所城市解封才能回去。

请分别求出来自 1 ~ n 城市的同学的回家日。

//想了很久,想到了a[i]表示第i点的a[i]天解封,想到了邻接表
//没想到//跟i相连的a[j]或者dist[i]大即可
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
int n,m,k;
int a[N];
int h[N],e[N],ne[N],idx;
int dist[N];
void add(int x,int y){
    e[idx]=y;
    ne[idx]=h[x];
    h[x]=idx++;
}
int spfa(){
//跟i相连的a[j]或者dist[i]大即可
    memset(dist,0x3f,sizeof dist);
    queue<int> q;
    dist[k]=a[k]; q.push(k);
    while(q.size()){
        int t=q.front(); q.pop();
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i], maxv = max(dist[t], a[j]);
            if(maxv < dist[j]) q.push(j), dist[j] = maxv;
        }
    }
    for(int i=1;i<n;i++) cout<<dist[i]<<" ";cout<<dist[n];
    return 0;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    memset(h,-1,sizeof h);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) {
        int f; cin>>f; a[f]=i;//第i天第f个城市解封
    };
    while(m--){
        int x,y; cin>>x>>y;
        add(x,y); add(y,x);
    }
    spfa();
    return 0;
}

考试将至,cofe 好好复习了一段时间后,准备写下试卷验证下自己的学习成果。由于 cofe 懒散的天性使他只想刷一套卷,便打算从 N 套卷子(编号 1−N)中选取题目来组一套。

一套题中有若干 难度-题号 的题目,题号各不相同,难度有 T1 到 T10 十个级别 。cofe 对每个难度的题都有一个期望数,即期望写这个难度题的数量。然而卷子是有限的,cofe 所期望的某个难度的题不一定能达到。于是组题时会优先使每个难度的题尽量先达到期望数。

而那些没有达到期望数的,只能选取其他难度的题从而保证实际总题数与期望总题数相等,这里cofe 给出一种选题策略。

  • 设没达到期望数的难度为 Ti,Ti 从小到大

  • 选取难度 >Ti 且难度最接近 Ti 的尚未选取的题目,若没得取,则取难度 <Ti 且难度最接近 Ti 的尚未选取的题目

  • 执行上一步的次数为取 Ti 的期望数与实际数的差值,取完后 Ti 增大

选取的具体题目则受输入的先后顺序影响,先输入的题目先取。

题目保证卷子总题数大于等于期望总题数。

//纯粹用vector的v[x].push_back({j,y})、v[j].front()、 v[j].erase(v[j].begin())
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int n,idx;
int a[15];
struct node{
    int difficulty;
    int juan;
    int timu;
}oo[10010];
bool cmp(node s1,node s2){
    if(s1.difficulty!=s2.difficulty) return s1.difficulty<s2.difficulty;
    if(s1.juan!=s2.juan) return s1.juan<s2.juan;
    return s1.timu<s2.timu;
}
int main()
{
    cin>>n;
    vector<PII> v[15];
    for(int i=1;i<=10;i++) cin>>a[i];//输入待取题目难度套数
    for(int j=1;j<=n;j++){
        int k;cin>>k;
        for(int i=0;i<k;i++){
            char c,s;
            int x,y;
            cin>>c>>x>>s>>y;
            v[x].push_back({j,y});//x有{题号y,第j套}
        }
    }
    for(int i=1;i<=10;i++){
        if(a[i]!=0){
            for(int j=i;j<=10;j++){
                while(v[j].size()){
                    PII k=v[j].front();
                    v[j].erase(v[j].begin());
                    oo[idx]={j,k.first,k.second};
                    idx++;
                    a[i]--;
                    if(a[i]==0) break;
                }
                if(a[i]==0) break;
            }
            if(a[i]!=0){
                for(int j=i-1;j>=1;j--){
                while(v[j].size()){
                    PII k=v[j].front();
                    v[j].erase(v[j].begin());
                    oo[idx]={j,k.first,k.second};
                    idx++;
                    a[i]--;
                    if(a[i]==0) break;
                }
                if(a[i]==0) break;
            }
            }
        }
    }
    sort(oo,oo+idx,cmp);
    int i;
    for(i=0;i<idx-1;i++){
        cout<<oo[i].juan<<"-"<<oo[i].timu<<" ";
    }
    cout<<oo[i].juan<<"-"<<oo[i].timu;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值