
2 5 8 1 2 3 1 3 2 1 4 5 2 3 1 2 5 3 3 4 2 3 5 4 4 5 3 1 5 5 6 2 3 1 3 2 1 3 1 10 4 5 2 5 2 7 5 2 7 4 1
3 2
#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
const int N = 1005;
const int inf = 1e9;
struct EDG
{
int v,d;
};
struct node
{
int v,c;
};
vector<EDG>mapt[N];
int spfa(int sp,int ep,int n)
{
int inq[N][2]={0},dis[N][3],num[N][2];
queue<node>q; //队列里面的节点都是需要更新的
node pre,now;
for(int i=1;i<=n;i++)
{
dis[i][0]=dis[i][1]=inf;
dis[i][2]=inf; //只是用于标记当前(i,0)组合点己更新过的值
num[i][0]=num[i][1]=0;
}
now.v=sp; now.c=0; dis[sp][0]=0; num[sp][0]=1; q.push(now);
while(!q.empty())
{
pre=q.front(); q.pop();
inq[pre.v][pre.c]=0;
if(pre.c==0) //为下次被替换到次小值时,是否需要再一次根据当前值更新作判断依居
dis[pre.v][2]=dis[pre.v][0];
int k=mapt[pre.v].size();
for(int i=0;i<k;i++)
{
now.v=mapt[pre.v][i].v;
if(dis[now.v][0]>=dis[pre.v][pre.c]+mapt[pre.v][i].d)
{
if(dis[now.v][0]>dis[pre.v][pre.c]+mapt[pre.v][i].d)
{
dis[now.v][1]=dis[now.v][0];
num[now.v][1]=num[now.v][0];
//当最小被替换成次小时,如果这个值没有更新过,就一定要放入队列
now.c=1;
if(inq[now.v][now.c]==0&&dis[now.v][now.c]!=dis[now.v][2])
q.push(now),inq[now.v][now.c]=1;
dis[now.v][0]=dis[pre.v][pre.c]+mapt[pre.v][i].d;
num[now.v][0]=num[pre.v][pre.c];
}
else num[now.v][0]+=num[pre.v][pre.c];
now.c=0;
if(inq[now.v][now.c]==0)
q.push(now),inq[now.v][now.c]=1;
}
else if(dis[now.v][1]>=dis[pre.v][pre.c]+mapt[pre.v][i].d)
{
if(dis[now.v][1]>dis[pre.v][pre.c]+mapt[pre.v][i].d)
{
dis[now.v][1]=dis[pre.v][pre.c]+mapt[pre.v][i].d;
num[now.v][1]=num[pre.v][pre.c];
}
else num[now.v][1]+=num[pre.v][pre.c];
now.c=1;
if(inq[now.v][now.c]==0)
q.push(now),inq[now.v][now.c]=1;
}
}
}
if(dis[ep][1]==dis[ep][0]+1)
num[ep][0]+=num[ep][1];
return num[ep][0];
}
int main()
{
int t,n,m,a;
EDG ss;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
mapt[i].clear();
while(m--)
{
scanf("%d%d%d",&a,&ss.v,&ss.d);
mapt[a].push_back(ss);
}
int sp,ep;
scanf("%d%d",&sp,&ep);
printf("%d\n",spfa(sp,ep,n));
}
}
HDU1688 Sightseeing(SPFA 求最短路与次短路的路径条数)可用作模板
原文:http://blog.csdn.net/u010372095/article/details/45118813