根据题意可得:关系友好时,BL-AL<=DL。关系不友好时,BD-AD>=DD(一定要注意题目说明了牛是按照编号站的,也就是递增的,所以方程都是大的牛位置减去小的牛位置)。那么发现这个是个差分约束系统,即:BL-AL<=DL,AD-BD<=-DD。那么以此建图,求出有负权最短路即可。
这里再说下差分约束系统,就是几个只含两个未知数,并且形如X-Y<=D这种形式的方程组。
当求最小值时,统一化成X-Y>=D,再求最长路即可。
差分约束系统:https://blog.csdn.net/consciousman/article/details/53812818
bellman-ford算法:这里顺带讲一下几个bellman-ford注意的点。
inq数组用来判断节点是否在队列内,为的是防止在记录出现次数的时候会多记录
松弛的时候有一个dis[u]<INF判断,这是防止用没有松弛过的点去松弛
#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e3+10;
int n,ml,md,u,v,w;
int dis[maxn],inq[maxn],cnt[maxn];
struct P
{
int to,cost;
};
vector<P> edge[maxn];
int bellman_ford()
{
queue<int> qu;
memset(inq,0,sizeof(inq));
memset(cnt,0,sizeof(cnt));
memset(dis,INF,sizeof(dis));
dis[1]=0;
inq[1]=1;
qu.push(1);
while(!qu.empty())
{
int u=qu.front();
qu.pop();
inq[u]=0;
for(int i=0; i<edge[u].size(); i++)
{
P v=edge[u][i];
if(dis[u]<INF && dis[v.to]>dis[u]+v.cost)
{
dis[v.to]=dis[u]+v.cost;
if(!inq[v.to])
{
qu.push(v.to);
inq[v.to]=1;
if(++cnt[v.to]>n) return -1;//存在负环,即无解
}
}
}
}
if(dis[n]==INF) return -2;//没有最短路,即无穷大
else return dis[n];
}
int main()
{
scanf("%d%d%d",&n,&ml,&md);
for(int i=1; i<=ml; i++)
{
scanf("%d%d%d",&u,&v,&w);
edge[u].push_back(P{v,w});
}
for(int i=1; i<=md; i++)//不友好的关系反向建边
{
scanf("%d%d%d",&u,&v,&w);
edge[v].push_back(P{u,-w});
}
printf("%d\n",bellman_ford());
return 0;
}