P蒜头君当大厨(差分约束)

问题描述

蒜头君苦练厨艺,终于成为了某高档酒店的大厨。 每天上班,蒜头君会被要求做 nnn
份菜。既然是高档酒店,那么客人们当然是很讲究的,尤其对于上菜的时间有很多要求。客人们的要求被分成下列四种: 菜品 a 的上菜时间必须比菜品
b的上菜时间早 d 分钟或者更早。 菜品 a的上菜时间必须比菜品 b的上菜时间迟 d分钟或者更迟。 菜品 a 的上菜时间在 d
分钟以后(包含 d 分钟)。 菜品 a 的上菜时间在 d 分钟之前(包含 d 分钟)。 蒜头君的上班时间记为 0
分钟。为了节约时间,在满足客人们要求的情况下,蒜头君希望最后上的一道菜的时间尽可能的早。(每道菜的上菜时间必须不早于蒜头君的上班时间)

输入格式

第一行输入一个整数 n,表示一共需要上 n 道菜。 第二行输入一个整数 m,表示客人们的要求数量。 接下里 m 行,每行先输入一个整数
op。 如果 op=1,表示描述里的第 1 种要求,后面跟着三个整数 a,b,d; 如果 op=2,表示描述里的第 2
种要求,后面跟着三个整数 a,b,d; 如果 op=3,表示描述里的第 3 种要求,后面跟着两个整数 a,d; 如果
op=4,表示描述里的第 4 种要求,后面跟着两个整数 a,d。 输出格式 能满足客人们的要求,输出最后一道菜的上菜时间;否则输出一行 I
can’t。

样例输入 1
3

5

2 3 2 10

2 2 1 2

2 3 2 5

1 2 3 7

3 3 9
样例输出 1
12
样例输入 2
3

4

3 1 3

2 3 1 9

2 1 3 -1

1 1 2 5
样例输出 2
I can’t

题解

裸的差分约束,注意下原点的连接方式!
初始时dis【0】=0 其他边为-1
再向每条边连一条长度为零的边

代码

#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
#define maxn 40005
int n,m;
int dis[maxn];
int End[maxn],Next[maxn],Len[maxn],Last[maxn];
int cnt;
void insert(int x,int y,int z)
{
    Next[++cnt]=Last[x];
    Last[x]=cnt;
    End[cnt]=y;
    Len[cnt]=z;
}
queue<int>q;
bool mark[maxn];
int ct[maxn];
bool flag=false;
void spfa()
{
    int i,j,k;
    for(i=1;i<=n;i++)dis[i]=-1;
    q.push(0);
    mark[0]=true;
    while(q.size())
    {

        int t=q.front();
        ct[t]++;
        if(ct[t]==n+1){
            flag=true;
            break;
        }
        q.pop();
        mark[t]=false;
        for(i=Last[t];i;i=Next[i])
        {
            int en=End[i];
            if(dis[t]+Len[i]>dis[en]){
                dis[en]=dis[t]+Len[i];
                if(mark[en]==false){
                    mark[en]=true;
                    q.push(en);
                }
            }
        }
    }
}
int main()
{
//  freopen("chef.in","r",stdin);
//  freopen("chef.out","w",stdout);
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)insert(0,i,0);
    for(i=1;i<=m;i++)
    {
        int x,a,b,d;
        scanf("%d",&x);
        if(x==1){
            scanf("%d%d%d",&a,&b,&d);
            insert(a,b,d);
        }
        if(x==2){
            scanf("%d%d%d",&a,&b,&d);
            insert(b,a,d);
        }
        if(x==3){
            scanf("%d%d",&a,&d);
            insert(0,a,d);
        }
        if(x==4){
            scanf("%d%d",&a,&d);
            insert(a,0,-d);
        }
    }
    spfa();
    int ans=0;
    if(flag==true){
        cout<<"I can't";
        return 0;
    }
    for(i=1;i<=n;i++)ans=max(ans,dis[i]);
    cout<<ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值