差分约束 - Partial Teacher - CodeForces 67A
题意:
老 师 分 糖 果 , 有 n 名 同 学 , 老师分糖果,有n名同学, 老师分糖果,有n名同学,
给 定 一 个 长 度 为 n − 1 的 字 符 串 , 由 ′ L ′ , ′ R ′ , ′ = ′ 组 成 , 给定一个长度为n-1的字符串,由'L','R','='组成, 给定一个长度为n−1的字符串,由′L′,′R′,′=′组成,
若 第 i 位 字 符 为 ′ L ′ , 则 表 示 第 i 位 同 学 的 成 绩 高 于 第 i + 1 位 同 学 的 成 绩 。 若第i位字符为'L',则表示第i位同学的成绩高于第i+1位同学的成绩。 若第i位字符为′L′,则表示第i位同学的成绩高于第i+1位同学的成绩。
若 第 i 位 字 符 为 ′ R ′ , 则 表 示 第 i + 1 位 同 学 的 成 绩 高 于 第 i 位 同 学 的 成 绩 。 若第i位字符为'R',则表示第i+1位同学的成绩高于第i位同学的成绩。 若第i位字符为′R′,则表示第i+1位同学的成绩高于第i位同学的成绩。
若 第 i 位 字 符 为 ′ = ′ , 则 表 示 第 i 位 同 学 的 成 绩 与 第 i + 1 位 同 学 的 成 绩 相 等 。 若第i位字符为'=',则表示第i位同学的成绩与第i+1位同学的成绩相等。 若第i位字符为′=′,则表示第i位同学的成绩与第i+1位同学的成绩相等。
成 绩 高 的 同 学 要 求 糖 果 数 量 多 于 相 邻 的 成 绩 较 低 的 同 学 。 成绩高的同学要求糖果数量多于相邻的成绩较低的同学。 成绩高的同学要求糖果数量多于相邻的成绩较低的同学。
每 位 同 学 至 少 分 得 一 个 糖 果 , 计 算 老 师 至 少 需 要 准 备 多 少 糖 果 。 每位同学至少分得一个糖果,计算老师至少需要准备多少糖果。 每位同学至少分得一个糖果,计算老师至少需要准备多少糖果。
输入:
首 行 包 括 一 个 正 整 数 n , 表 示 学 生 的 数 量 , 首行包括一个正整数n,表示学生的数量, 首行包括一个正整数n,表示学生的数量,
接 着 输 入 一 个 长 度 为 n − 1 的 字 符 串 , 表 示 相 邻 两 个 同 学 之 间 的 关 系 。 接着输入一个长度为n-1的字符串,表示相邻两个同学之间的关系。 接着输入一个长度为n−1的字符串,表示相邻两个同学之间的关系。
输出:
一 个 正 整 数 , 表 示 老 师 至 少 需 要 准 备 的 糖 果 的 数 量 。 一个正整数,表示老师至少需要准备的糖果的数量。 一个正整数,表示老师至少需要准备的糖果的数量。
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 2 ≤ n ≤ 1000
分析:
裸 的 差 分 约 束 题 , 记 第 i 个 同 学 得 到 的 糖 果 数 量 为 C i , 裸的差分约束题,记第i个同学得到的糖果数量为C_i, 裸的差分约束题,记第i个同学得到的糖果数量为Ci,
要 求 最 小 值 , 跑 最 长 路 , 将 不 等 式 转 化 为 A ≥ B + k 的 形 式 。 要求最小值,跑最长路,将不等式转化为A≥B+k的形式。 要求最小值,跑最长路,将不等式转化为A≥B+k的形式。
① 、 L : C i ≥ C i + 1 + 1 , 建 边 : i + 1 − > i , 边 权 为 1 ①、L:C_i≥C_{i+1}+1,建边:i+1->i,边权为1 ①、L:Ci≥Ci+1+1,建边:i+1−>i,边权为1
② 、 R : C i + 1 ≥ C i + 1 , 建 边 : i − > i + 1 , 边 权 为 0 ②、R:C_{i+1}≥C_i+1,建边:i->i+1,边权为0 ②、R:Ci+1≥Ci+1,建边:i−>i+1,边权为0
③ 、 = : 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+1即Ci≥Ci+1且Ci+1≥Ci,建边:i−i+1,无向边,边权为0。
④ 、 C i ≥ 1 ④、C_i≥1 ④、Ci≥1
由 于 图 不 一 定 连 通 , 因 此 我 们 需 要 遍 历 所 有 未 被 计 算 过 的 点 。 由于图不一定连通,因此我们需要遍历所有未被计算过的点。 由于图不一定连通,因此我们需要遍历所有未被计算过的点。
建 立 虚 拟 源 点 0 似 乎 会 T L E , 要 避 免 重 复 更 新 同 一 个 点 , 建立虚拟源点0似乎会TLE,要避免重复更新同一个点, 建立虚拟源点0似乎会TLE,要避免重复更新同一个点,
由 于 需 要 保 证 条 件 ④ , 我 们 每 次 从 未 被 计 算 过 的 点 开 始 跑 一 遍 单 源 最 短 路 , 源 点 的 d i s 初 始 化 为 1 即 可 。 由于需要保证条件④,我们每次从未被计算过的点开始跑一遍单源最短路,源点的dis初始化为1即可。 由于需要保证条件④,我们每次从未被计算过的点开始跑一遍单源最短路,源点的dis初始化为1即可。
因 为 所 有 边 的 权 值 都 是 大 于 等 于 0 的 , 就 能 够 保 证 其 他 点 的 d i s 大 于 等 于 1. 因为所有边的权值都是大于等于0的,就能够保证其他点的dis大于等于1. 因为所有边的权值都是大于等于0的,就能够保证其他点的dis大于等于1.
注意:
跑 最 长 路 , 距 离 数 组 应 当 初 始 化 一 个 较 小 的 值 。 跑最长路,距离数组应当初始化一个较小的值。 跑最长路,距离数组应当初始化一个较小的值。
代码:
#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;
}