题目链接:http://poj.org/problem?id=2387
/*
可以判定负环,负权边的spfa算法 BFS版本用于计算最短路径
*/
# include <iostream>
# include <string.h>
# include <string>
# include <algorithm>
# include <stdio.h>
# include <queue>
# include <set>
# define INFI 0x3f3f3f3f
# define MAXN 2005
using namespace std;
typedef struct Node
{
int to; //一条路的终点
int w;//长度
}Node;
int sum = 0,cnt=0;//LLL 优化
int m,n;
int inq[MAXN];//是否在队列之中
int lowcost[MAXN];//记录最短路径
int num[MAXN];
vector<Node > vt[MAXN];//存储地图信息
int spfa(int x)
{
for(int i=1; i<=n; ++i)
{
lowcost[i] = INFI;
inq[i] = 0;
num[i] = 0;
}
lowcost[x] = 0;
deque<int > que;//双向队列,可插入头部和尾部
que.push_back(n);
inq[x] = 1;//是否在队列之中
num[x] = cnt = 1;
while(!que.empty())
{
int t = que.front();
que.pop_front();
if(lowcost[t] * cnt > sum)
{
que.push_back(t);
continue;
}
sum -= lowcost[t];
cnt--;
inq[t] = 0;
for(int i=0; i<vt[t].size(); ++i)
{
int ed = vt[t][i].to;
int len = vt[t][i].w;
if(lowcost[ed] > lowcost[t] + len)
{
lowcost[ed] = lowcost[t] + len;
if(!inq[ed])
{
inq[ed] = 1;
//SLF 优化,最短距离最小的放在队首
if(!que.empty() && lowcost[que.front()] > lowcost[ed])
que.push_front(ed);
else
que.push_back(ed);
sum += lowcost[ed];
cnt++;
num[ed]++;
if(num[ed] >= n)//BFS判定负环:存在一点的入队次数大于n
return 1;
}
}
}
}
return 0;
}
int main(void)
{
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin >> m >> n;
for(int i=0; i<m; ++i)
{
int a,b,c;
cin >> a >> b>> c;
Node d;
d.w = c;
d.to = b;
vt[a].push_back(d);
d.to = a;
vt[b].push_back(d);
}
//应题目要求,判断从n到1的最短路径
int fuhuan = spfa(n);
cout << lowcost[1]<<endl;
return 0;
}
/*
DFS版本 用于判断是否存在负环
*/
# include <bits/stdc++.h>
# define MAXN 100000
# define INFI 0x3f3f3f3f
using namespace std;
typedef struct Node
{
int v;
int len;
}Node;
int n,m;
vector<Node > vt[MAXN];
int vis[MAXN],flg=0;
int num[MAXN];
int lowcost[MAXN];
stack<int > stk;
void spfa(int t)
{
if(flg) return;
vis[t] = 1;
for(int i=0; i<vt[t].size(); ++i)
{
int ed = vt[t][i].v;
int len = vt[t][i].len;
if(lowcost[ed] > lowcost[t] + len)
{
lowcost[ed] = lowcost[t] + len;
if(!vis[ed])
{
spfa(ed);
}
else
{
flg = 1;
return;
}
}
}
vis[t] = 0;
return ;
}
int main(void)
{
// freopen("in.txt","r",stdin);
cin >> n >> m;
Node t;
for(int i=0; i<m; ++i)
{
int a,b,c;
cin >> a >> b >> c;
t.v = b;
t.len = c;
vt[a].push_back(t);
}
for(int i=0; i<=n; ++i)
{
lowcost[i] = INFI;
num[i] = 0;
}
lowcost[1] = 0;
cout << spfa(1) << endl;;
return 0;
}