analysis
首先题目给的两个不等式需要列出来:
{
d
i
s
[
B
i
]
−
d
i
s
[
A
i
]
<
=
D
i
(
i
∈
[
1
,
M
L
]
)
d
i
s
[
B
i
]
−
d
i
s
[
A
i
]
>
=
D
i
(
i
∈
[
M
L
+
1
,
M
L
+
M
D
]
)
\begin{cases} dis[B_i]-dis[A_i]<=D_i(i\in[1,M_L])\\ dis[B_i]-dis[A_i]>=D_i(i\in[M_L+1,M_L+M_D])\\ \end{cases}
{dis[Bi]−dis[Ai]<=Di(i∈[1,ML])dis[Bi]−dis[Ai]>=Di(i∈[ML+1,ML+MD])
这个时候设
d
i
s
[
1
]
=
0
dis[1]=0
dis[1]=0,跑一次差分约束就可以过(了吗?)
实际上仅考虑上面的不等式的话就漏掉了一个条件:奶牛们按照编号顺序来排队
于是每一头奶牛和其相邻的奶牛之间应该连一条边:
d
i
s
[
i
]
−
d
i
s
[
i
+
1
]
<
=
0
dis[i]-dis[i+1]<=0
dis[i]−dis[i+1]<=0
于是这样就可以过了吗?No
你还没有考虑图是否连通呢!
有可能上面的不等式构成的图并不连通,牛1和牛n之间可能并没有直接的约束关系,但这并不代表应该输出-2(也就是任意大),因为可能这个图的某个不和1连通的分图内有无解的情况,所以这个时候应该考虑如何解决图不连通的问题
解决办法就是,先假设差分约束系统有一组全为负数的解,然后从0向所有点连一条权值为0的边,这样先从0跑一次spfa判断有没有解,然后再从1跑即可(这个时候就算原来那个图不是所有都和1连通的也没有关系了,毕竟这个时候我们只考虑点1和点n的关系,那个spfa(0)只是为了排除和1,n无关的其他点无解的情况)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
template<typename T>void read(T &x){
char r=getchar();T neg=1;x=0;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
int n,ml,md;
const int maxm=10010<<1;
const int maxn=1010;
struct node{
int e;
int w;
int nxt;
}edge[maxm<<2];
int head[maxn];
int cnt=0;
inline void addl(int u,int v,int w){
edge[cnt].e=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
int dis[maxn];
int in[maxn];
bool insta[maxn];
queue<int>q;
int flag=0x3f3f3f3f;
void spfa(int st){
clean(dis,0x3f);
clean(in,0);
clean(insta,0);
q.push(st);
insta[st]=true;
++in[st];
dis[st]=0;
while(q.empty()==false){
int f=q.front();
q.pop();
insta[f]=false;
for(int i=head[f];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(dis[v]>dis[f]+edge[i].w){
dis[v]=dis[f]+edge[i].w;
if(!insta[v]){
insta[v]=true;
q.push(v);
if(++in[v]>n){
flag=-1;
return;
}
}
}
}
}
if(dis[n]>=0x3f3f3f3f)
flag=-2;
else flag=dis[n];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("layout.6.in","r",stdin);
#endif
clean(head,-1);
read(n);
read(ml);
read(md);
loop(i,1,ml){
int ai,bi,di;
read(ai);
read(bi);
read(di);
addl(ai,bi,di);
}
loop(i,1,md){
int ai,bi,di;
read(ai);
read(bi);
read(di);
addl(bi,ai,-di);
}
loop(i,1,n-1)
addl(i+1,i,0);
loop(i,1,n)
addl(0,i,0);
spfa(0);
if(flag==-1){
printf("%d\n",flag);
return 0;
}
spfa(1);
printf("%d\n",dis[n]>=0x3f3f3f3f?-2:dis[n]);
return 0;
}