题357.差分约束-acwing-Q3265–再卖菜
一、题目
二、题解
本题的突破点在去尾法取整求平均值那,因为是去尾法,因此设第一天价格为vi,我们可以想到当i>=2时,计算第二天价格vi'时,有:
vi'=(vi-1+vi+vi+1)/3=>3vi‘≤vi-1+vi+vi+1≤3vi’+2
出现了不等式约束,因此为求满足所有不等式约束的解的问题,显然考虑使用差分约束来做。
由于上不等式有多个变量,不符合差分约束的一般不等式约束,又由于是相邻变量求和,所以我们想到用前缀和替换几个变量相加,设Si为到i家店第一天价格的前缀和,则有:
3vi‘≤Si+1-Si-2≤3vi’+2
由于该问题要求解字典序最小,因此求最长路,则将上不等式变形为:
Si+1≥Si-2+3vi’,即从i-2往i+1连一条权为3vi‘的边
Si-2≥Si+1-(3vi’+2),即从i+1往i-2连一条权为-(3vi’+2)的边
又这里价格明确是正整数,则有Si-Si-1≥1,即:
Si≥Si+1+1,即从i–1往i连一条边权为1的边
再单独考虑作为特殊情况的i=1和n,同理可得下不等式:
i=1有
S0≥S2-(2vi’+1)
S2≥S0+2vi’
i=n有
Sn-2≥Sn+2vi’
Sn≥Sn-2-(2vi'+1)
以上为相对关系,最后考虑绝对关系,易知有S0=0。
根据上述不等式连边建图,spfa求解dist即可,因为本题保证有解,所以在写的时候按求最长路直接写即可,不用判正环。具体代码如下:
#include <bits/stdc++.h>
using namespace std;
const int Inf=0x3f3f3f3f;
const int maxn=330,maxm=3*maxn;
int n;
int v[maxn];
int h[maxn],e[maxm],w[maxm],ne[maxm],idx;
int dist[maxn],book[maxn];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void spfa()
{
memset(dist,-Inf,sizeof dist);
queue<int> q;
q.push(0);
dist[0]=0;book[0]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
book[t]=0;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]<dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!book[j])
{
q.push(j);
book[j]=1;
}
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>v[i];
}
memset(h,-1,sizeof h);
add(2,0,-(2*v[1]+1)),add(0,2,2*v[1]);//
for(int i=2;i<n;i++)
{
add(i-2,i+1,3*v[i]),add(i+1,i-2,-(3*v[i]+2));//
}
add(n-2,n,2*v[n]),add(n,n-2,-(2*v[n]+1));//
for(int i=1;i<=n;i++)
{
add(i-1,i,1);//
}
spfa();
for(int i=1;i<=n;i++)
{
cout<<dist[i]-dist[i-1]<<" ";
}
}