刷刷水题,莫笑莫笑
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define swap(t,a,b) (t=a,a=b,b=t)
const int E=20002;
const int V=1001;
const int INF=1<<30;
struct EDGE
{
int link,val,next;
} edge[E];
int head[V],cnt[V],dist[V],e;
bool vis[V];
void addedge(int a,int b,int c)
{
edge[e].link=b;
edge[e].val=c;
edge[e].next=head[a];
head[a]=e++;
}
int relax(int u,int v,int c)
{
if(dist[v]>dist[u]+c)
{
//求的是最大值,若求最小值,反号
dist[v]=dist[u]+c;
return 1;
}
return 0;
}
int SPFA(int src,int n)
{
memset(vis,false,sizeof(vis));
memset(cnt,0,sizeof(cnt));
for(int i=1; i<=n; ++i) dist[i]=INF;
dist[src]=0;
vis[src]=true;
queue<int> q;
q.push(src);
++cnt[src];
while(!q.empty())
{
int u,v;
u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].link;
if(relax(u,v,edge[i].val)==1&&!vis[v])
{//如果不用relax函数,!VIS[V]的判断应该写在这
q.push(v);
vis[v]=true;
if((++cnt[v])>n) return -1;//cnt[i]为入队列次数,用来判断是否存在负权回路
}
}
}
if(dist[n]==INF) return -2;
// src与n不可达,有些题目可省!!!
return dist[n];
//返回src到n的最短距离,根据题意不同而改变
}
int main()
{
int n, x, y;
int T;
int a, b, c;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n, &x, &y);
e=0;
memset(head,-1,sizeof(head));
for(int i = 1; i <= x; i++)
{
scanf("%d%d%d", &a, &b, &c);
//b - a <= c
addedge(a, b, c);
}
for(int i = 1; i <= y; i++)
{
scanf("%d%d%d", &a, &b, &c);
//b - a >= c a - b <= -c
addedge(b, a, -c);
}
printf("%d\n",SPFA(1, n));
}
return 0;
}