差分约束 - Partial Teacher - CodeForces 67A

差分约束 - Partial Teacher - CodeForces 67A

题意:

老 师 分 糖 果 , 有 n 名 同 学 , 老师分糖果,有n名同学, n

给 定 一 个 长 度 为 n − 1 的 字 符 串 , 由 ′ L ′ , ′ R ′ , ′ = ′ 组 成 , 给定一个长度为n-1的字符串,由'L','R','='组成, n1L,R,=

若 第 i 位 字 符 为 ′ L ′ , 则 表 示 第 i 位 同 学 的 成 绩 高 于 第 i + 1 位 同 学 的 成 绩 。 若第i位字符为'L',则表示第i位同学的成绩高于第i+1位同学的成绩。 iLii+1

若 第 i 位 字 符 为 ′ R ′ , 则 表 示 第 i + 1 位 同 学 的 成 绩 高 于 第 i 位 同 学 的 成 绩 。 若第i位字符为'R',则表示第i+1位同学的成绩高于第i位同学的成绩。 iRi+1i

若 第 i 位 字 符 为 ′ = ′ , 则 表 示 第 i 位 同 学 的 成 绩 与 第 i + 1 位 同 学 的 成 绩 相 等 。 若第i位字符为'=',则表示第i位同学的成绩与第i+1位同学的成绩相等。 i=ii+1

成 绩 高 的 同 学 要 求 糖 果 数 量 多 于 相 邻 的 成 绩 较 低 的 同 学 。 成绩高的同学要求糖果数量多于相邻的成绩较低的同学。

每 位 同 学 至 少 分 得 一 个 糖 果 , 计 算 老 师 至 少 需 要 准 备 多 少 糖 果 。 每位同学至少分得一个糖果,计算老师至少需要准备多少糖果。

输入:

首 行 包 括 一 个 正 整 数 n , 表 示 学 生 的 数 量 , 首行包括一个正整数n,表示学生的数量, n

接 着 输 入 一 个 长 度 为 n − 1 的 字 符 串 , 表 示 相 邻 两 个 同 学 之 间 的 关 系 。 接着输入一个长度为n-1的字符串,表示相邻两个同学之间的关系。 n1

输出:

一 个 正 整 数 , 表 示 老 师 至 少 需 要 准 备 的 糖 果 的 数 量 。 一个正整数,表示老师至少需要准备的糖果的数量。

Examples
Input

5
LRLR

Output

2 1 2 1 2

Input

5
=RRR

Output

1 1 2 3 4

数据范围:

2   ≤   n   ≤   1000 2 ≤ n ≤ 1000 2n1000


分析:

裸 的 差 分 约 束 题 , 记 第 i 个 同 学 得 到 的 糖 果 数 量 为 C i , 裸的差分约束题,记第i个同学得到的糖果数量为C_i, iCi

要 求 最 小 值 , 跑 最 长 路 , 将 不 等 式 转 化 为 A ≥ B + k 的 形 式 。 要求最小值,跑最长路,将不等式转化为A≥B+k的形式。 AB+k

① 、 L : C i ≥ C i + 1 + 1 , 建 边 : i + 1 − > i , 边 权 为 1 ①、L:C_i≥C_{i+1}+1,建边:i+1->i,边权为1 LCiCi+1+1i+1>i1

② 、 R : C i + 1 ≥ C i + 1 , 建 边 : i − > i + 1 , 边 权 为 0 ②、R:C_{i+1}≥C_i+1,建边:i->i+1,边权为0 RCi+1Ci+1i>i+10

③ 、 = : C i = C i + 1 即 C i ≥ C i + 1 且 C i + 1 ≥ C i , 建 边 : i − i + 1 , 无 向 边 , 边 权 为 0 。 ③、=:C_i=C_{i+1}即C_i≥C_{i+1}且C_{i+1}≥C_i,建边:i-i+1,无向边,边权为0。 =Ci=Ci+1CiCi+1Ci+1Ci:ii+10

④ 、 C i ≥ 1 ④、C_i≥1 Ci1

由 于 图 不 一 定 连 通 , 因 此 我 们 需 要 遍 历 所 有 未 被 计 算 过 的 点 。 由于图不一定连通,因此我们需要遍历所有未被计算过的点。

建 立 虚 拟 源 点 0 似 乎 会 T L E , 要 避 免 重 复 更 新 同 一 个 点 , 建立虚拟源点0似乎会TLE,要避免重复更新同一个点, 0TLE

由 于 需 要 保 证 条 件 ④ , 我 们 每 次 从 未 被 计 算 过 的 点 开 始 跑 一 遍 单 源 最 短 路 , 源 点 的 d i s 初 始 化 为 1 即 可 。 由于需要保证条件④,我们每次从未被计算过的点开始跑一遍单源最短路,源点的dis初始化为1即可。 dis1

因 为 所 有 边 的 权 值 都 是 大 于 等 于 0 的 , 就 能 够 保 证 其 他 点 的 d i s 大 于 等 于 1. 因为所有边的权值都是大于等于0的,就能够保证其他点的dis大于等于1. 0dis1.

注意:

跑 最 长 路 , 距 离 数 组 应 当 初 始 化 一 个 较 小 的 值 。 跑最长路,距离数组应当初始化一个较小的值。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

const int N=1010, M=4*N, inf=0x3f3f3f3f;

int n;
int e[M],ne[M],w[M],h[N],idx;
int dis[N];
bool st[N];
char str[N];

void add(int a,int b, int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void spfa(int S)
{
    queue<int> Q;
    Q.push(S);
    dis[S]=1;
    st[S]=true;

    while(Q.size())
    {
        int u=Q.front();
        Q.pop();
        st[u]=false;
        for(int i=h[u];~i;i=ne[i])
        {
            int j=e[i];
            if(dis[j]<dis[u]+w[i])
            {
                dis[j]=dis[u]+w[i];
                if(!st[j])
                {
                    st[j]=true;
                    Q.push(j);
                }
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    scanf("%s",str+1);

    memset(h,-1,sizeof h);
    for(int i=1;i<n;i++)
        if(str[i]=='L') add(i+1,i,1);  //i>=(i+1)+1
        else if(str[i]=='R') add(i,i+1,1);
        else add(i,i+1,0), add(i+1,i,0);

    memset(dis,-1,sizeof dis);
    for(int i=1;i<=n;i++)
        if(dis[i]==-1)
            spfa(i);
    
    for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值