n n n个人排队
x x x个相互喜欢的关系,表示 d i s [ u ] − d i s [ v ] < = w dis[u]-dis[v]<=w dis[u]−dis[v]<=w
y y y个相互厌恶的关系,表示 d i s [ u ] − d i s [ v ] > = w dis[u]-dis[v]>=w dis[u]−dis[v]>=w
d i s [ u ] < = d i s [ v ] + w dis[u]<=dis[v]+w dis[u]<=dis[v]+w
那么 v v v向 u u u连一条权值 w w w的边
d i s [ v ] < = d i s [ u ] − w dis[v]<=dis[u]-w dis[v]<=dis[u]−w
那么 u u u向 v v v连一条边权 − w -w −w的边
而且需要满足 d i s [ i ] > = d i s [ i − 1 ] dis[i]>=dis[i-1] dis[i]>=dis[i−1]
那么 i i i向 i − 1 i-1 i−1连一条边权 0 0 0的边
然后跑最短路,即可
若最后 d i s [ n ] dis[n] dis[n]仍然是 i n f inf inf,说明没有限制条件,可以无限远
若有负环存在,会一直在环里减小,其实是无解的
#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int maxn = 2e6+10;
int t,n,q,qq;
struct edge{
int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
int dis[maxn],vis[maxn],shu[maxn];
void add(int u,int v,int w){
d[++cnt] = (edge){v,head[u],w},head[u] = cnt;
}
int spfa(int s)
{
for(int i=1;i<=n;i++) dis[i] = inf, vis[i] = shu[i] = 0;
queue<int>q; dis[s] = 0; q.push( s );
while( !q.empty() )
{
int u = q.front(); q.pop();
vis[u] = 0;
for(int i=head[u];i;i=d[i].nxt )
{
int v = d[i].to;
if( dis[v]>dis[u]+d[i].w )
{
dis[v] = dis[u]+d[i].w;
if( !vis[v] )
{
vis[v] = 1, q.push( v );
if( ++shu[v]==n ) return -1;
}
}
}
}
if( dis[n]==inf ) return -2;
return dis[n];
}
int main()
{
cin >> t;
while( t-- )
{
cin >> n >> q >> qq;
for(int i=2;i<=n;i++) add(i,i-1,0);
for(int i=1;i<=q;i++)
{
int l,r,w; scanf("%d%d%d",&l,&r,&w);
add(l,r,w);
}
for(int i=1;i<=qq;i++)
{
int l,r,w; scanf("%d%d%d",&l,&r,&w);
add(r,l,-w);
}
cout << spfa(1) << endl;
cnt = 1;
for(int i=1;i<=n;i++) head[i] = 0;
}
}