这题还是用的 SPFA + 栈 过的,400多ms,写得多了,发现都可以套用模块了,除了输入不太一样外,其他的都基本一样。
模块一:负责各个数组的初始化
模块二:负责加边,对边用邻接表处理
模块三:SPFA 用栈来实现的过程
代码
#include<stdio.h>
#include<stdlib.h>
#define INF 0xfffffff
#define NN 1004
#define MM 20004
int edNum, N;
int next[MM];
int root[NN];
int mark[NN];
int cnt[NN];
int dis[NN];
int stack[NN];
struct node{
int e, v;
}edge[MM];
/*在这里我用了一个函数来完成初始化,也可以看着一个固定模块了*/
/*模块一*/
void Init(){
int i;
for (i = 0; i <= N; i++){
root[i] = -1;
mark[i] = 0;
cnt[i] = 0;
}
}
/*模块二*/
void add(int a, int b, int c){
edge[edNum].e = b;
edge[edNum].v = c;
next[edNum] = root[a];
root[a] = edNum++;
}
/*函数返回-1,表示有负边权回路,就表示不可能
函数返回-2,就表示起点到终点的距离不定,这里用dis[N] == INF,来判断,因为开始就是赋值的是INF
否者,返回dis[N],这里面存的就是起点到终点的最大距离
*/
/*模块三*/
int Spfa()
{
int i, top, cur, tmp, nxt;
top = 0;
for (i = 1; i <= N; i++){
dis[i] = INF;
if (root[i] != -1){
stack[++top] = i;
cnt[i]++;
mark[i] = 1;
}
}
dis[1] = 0;
while (top){
cur = stack[top--];
tmp = root[cur];
mark[cur] = 0;
while (tmp != -1){
nxt = edge[tmp].e;
if (dis[nxt] > dis[cur] + edge[tmp].v){
dis[nxt] = dis[cur] + edge[tmp].v;
if (!mark[nxt]){
cnt[nxt]++;
if (cnt[nxt] > N + 1){
return -1;
}
mark[nxt] = 1;
stack[++top] = nxt;
}
}
tmp = next[tmp];
}
}
if (dis[N] == INF){
return -2;
}
return dis[N];
}
int main()
{
int ML, MD, a, b, c;
scanf("%d%d%d", &N, &ML, &MD);
Init();
while (ML--){
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
while (MD--){
scanf("%d%d%d", &a, &b, &c);
add(b, a, -c);
}
printf("%d\n", Spfa());
//system("pause");
return 0;
}