【图-差分约束】站队列比赛

本文介绍了一种基于区间查分约束的算法问题,通过构建图模型并运用SPFA算法求解最短路径来确定满足特定条件的队列长度最小值。文章详细解释了解题思路与步骤,并提供了完整的代码实现。
  • 题目描述

    体育周即将结束,学校有一个事多的朱老师,提出了一个附加的活动项目,要求每个班
    按他的要求站队列, 比赛的结果不是按照队列站的是否整齐, 而是按他的要求展成的队列后,
    人数多少来评价。
    具体要求:
    1、在操场上画一条线,并在该线画上标号(1 到 n)
    2、事先不告诉队列的长度(即人数) ,但告诉在某些标号之间(区间)至少有多少个同
    学(同学只能站在标号上) ,用区间[ai,bi,ci]来描述它,[ai,bi,ci]表示在该队列中处于[ai,bi]这
    个区间的同学至少有 ci 个,现在给出若干个这样的区间,让每个班级按照这些区间要求去
    站队列,满足条件的队列长度最少的班级(即人数最少)为获胜班,小岳岳最后一次请求你
    的帮助。

  • 输入格式
    第一行包括一个整数 n(n≤1000) ,表示区间个数;
    以下 n 行每行描述这些区间,第 1+i 行三个整数 ai,bi,ci ,由空格隔开,其中 0≤ai
    ≤bi≤1000 而且 1≤ci≤bi-ai+1.
  • 输出格式
    只有一个整数表示满足要求队列长度的最小值,如果不存在则输出-1.
  • 样例输入

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

  • 样例输出

6

这题是从poj1201改的,加了一个输出-1。
传送门:poj1201

这题是一个挺弱的区间查分约束。
设d[i] 是第i位之前的最小值;
先根据题意给ai bi ci 满足 d[ai]-d[bi]>=c[i];
然后因为题中的(同学只能站在标号上) 有d[i+1]-d[i]>=0;
d[i+1]-d[i]<=1;

所以有:
d[ai]-d[bi]>=c[i];
d[i+1]-d[i]>=0;
d[i]-d[i+1]>=-1;
根据差分约束条件构图,用spfa跑最长路,判断负环时输出-1即可。
代码:

#include <iostream>
#include <queue>
#include <climits>
#include <cstdio>
#include <cstring>
#define INF 0xffffff
#define MAXARR 5000
#define WRONG -66666
using namespace std;
struct edge{
    int from,to,val;
};
vector<edge> e;
vector<int> node[MAXARR];
int n=0;
int MIN=INT_MAX,MAX=INT_MIN;
int s[MAXARR]={0};
void add_edge(int u,int v,int val)
{
    e.push_back((edge){u,v,val});
    node[u].push_back(n++);
}
int spfa()
{
    queue<int> q;
    int used[MAXARR]={0};
    int d[MAXARR]={0};
    fill(d+MIN,d+MAX,-INF);
    q.push(MIN);
    used[MIN]=1;
    d[MIN]=0;
    int sum[MAXARR];
    memset(sum,0,sizeof(sum));
    sum[MIN]++;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        used[u]=0;
        if(sum[u]>MAX)
            return WRONG;
        for(int i=0;i<node[u].size();i++)
        {
            if(d[e[node[u][i]].to]<d[u]+e[node[u][i]].val){
                d[e[node[u][i]].to]=d[u]+e[node[u][i]].val;
                if(!used[e[node[u][i]].to])
                {
                    used[e[node[u][i]].to]=1;
                    q.push(e[node[u][i]].to);
                    sum[e[node[u][i]].to]++;
                }
            }
        }
    }
    return d[MAX];
}
int main()
{
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        MIN=min(a,MIN);
        MAX=max(b+1,MAX);
        add_edge(a,b+1,c);
    }
    for(int i=MIN;i<MAX;i++)
    {
        add_edge(i,i+1,0);
        add_edge(i+1,i,-1);
    }
    int temp=spfa();
    if(temp==WRONG) {cout<<-1<<endl;return 0;}
    cout<<temp<<endl;
    return 0;
}

p.s. 写题时边数组开小了。。。。RE了。。。。改成5000AC。

首页 题库 训练 比赛 作业 讨论 评测记录 排名 算法基础 2032kehaochen G. 【模拟试题】正确答案 传统题 1000ms 256MiB 问题描述 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案。 “吔,我的答案和你都不一样!”,小Y说道,”我们去找神犇们问答案吧”。 外卡组试卷中共有m道判断题,小H与小Y一共从其他n个神犇那问了答案。之后又从小G那里得知,这n个神犇中有p个考了满分,q个考了零分,其他神犇不为满分或零分。这可让小Y与小H犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小的那个。无解输出-1。 输入格式 第一行四个整数n, m, p, q,意义如上描述。 接下来n行,每一行m个字符’N’或’Y’,表示这题这个神犇的答案。 输出格式 仅一行,一个长度为m的字符串或是-1。 样例1 输入数据 1 2 2 2 0 YY YY 输出数据 1 YY 数据范围 对于 30%的数据,n <= 100; 对于 60%的数据,n <= 5000 , m <= 100; 对于 100%的数据,1 <= n <= 30000 , 1 <= m <= 500. 0 <= p , q 且 p + q <= n。 进入在线编程模式 (Alt+E) 递交 【G2032】模拟训练 已认领 查看作业 成绩表 我的最近递交记录 帮助 状态正在进行…题目8开始时间2025-10-28 0:00截止时间2025-11-5 23:59可延期24 小时 状态 评测队列 服务状态 开发 开源 支持 帮助 联系我们 关于 关于 隐私 服务条款 版权申诉 Language 兼容模式 主题 Worker 0, 12msPowered by Hydro v5.0.0-beta.9 Community ```cpp#include<bits/stdc++.h> using namespace std; map<string,int> f; string Translation(string s1){ string temporary=s1; for(int i=0; i<temporary.size(); i++){ if(temporary[i]=='Y'){ temporary[i]='N'; } else{ temporary[i]='Y'; } } return temporary; } int main(){ int N,M,P,Q; scanf("%d%d%d%d",&N,&M,&P,&Q); vector<string> s(N+5); for(int i=1; i<=N; i++){ cin >>s[i]; f[s[i]]++; } set<string> st; for(int i=1; i<=N; i++){ st.insert(s[i]); st.insert(Translation(s[i])); } for(auto mfy:st){ int Left=f[mfy]; int Right=f[Translation(mfy)]; if(Left>=P&&Right>=Q){ cout <<mfy << endl; return 0; } } printf("-1\n"); return 0; }```代码有问题
11-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值