这题还是用的 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 ;
}
#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 ;
}