将查分约束系统问题转换成有向图的最短路问题,用BF算法求1号节点到N号节点的最短路长度,其中包含判断负环的情况,在该情况下要退出寻找最短路的循环,一开始没有注意这个条件,可想而知会死循环超时。
#include <stdio.h>
#include <vector>
using namespace std;
#define MAX_V 1200
#define INF 0x7FFFFFFF
typedef struct edge{
int from;
int to;
int len;
edge(int from, int to, int len){
this->from = from;
this->to = to;
this->len = len;
}
}edge;
vector<edge> edges;
int dis[MAX_V];
void solve(int N){
//BF算法进行单源最短路计算
int i, cnt;
bool update;
edge e(0,0,0);
for(i=1; i<=N; i++)
dis[i] = INF;
dis[1] = 0;
cnt = 0;
while(1){
update = false;
for(i=0; i<edges.size(); i++){
e = edges[i];
if(INF!=dis[e.from] && dis[e.from]+e.len<dis[e.to]){
dis[e.to] = dis[e.from]+e.len;
update = true;
}
}
//没法再更新最短路径,可退出循环了
if(!update)
break;
cnt++;
if(cnt==N && update){
//第N次还进行了更新,说明有负环,应该跳出循环
break;
}
}
if(dis[1] < 0){
//有负环,无解
printf("-1\n");
return;
}
if(INF == dis[N]){
//解无限大
printf("-2\n");
return;
}
printf("%d\n", dis[N]);
}
int main(void){
int N, ML, MD, i;
int a, b, len;
//freopen("input.dat", "r", stdin);
while(EOF != scanf("%d %d %d", &N, &ML, &MD)){
edges.clear();
while(ML--){
scanf("%d %d %d", &a, &b, &len);
//BL-AL<=len的情况,连接一条AL到BL的有向边
edges.push_back(edge(a, b, len));
}
while(MD--){
scanf("%d %d %d", &a, &b, &len);
//AD-BD<=-DD的情况,连接一条从BD到AD的有向边
edges.push_back(edge(b, a, -1*len));
}
//从i+1号节点到i号节点的边权值为0(因为dis[i]-dis[i+1]<=0)
for(i=1; i<=N-1; i++){
edges.push_back(edge(i+1, i, 0));
}
solve(N);
}
return 0;
}