问题描述
蒜头君苦练厨艺,终于成为了某高档酒店的大厨。 每天上班,蒜头君会被要求做 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;
}