题357.差分约束-acwing-Q3265--再卖菜


题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]<<" ";
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值