dijkstra求最短路和次短路的求法和计算 模板
dijkstra求最短路的变形。
外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次。
算法:
1、如果比最短路短就更新最短路和次短路。
2、如果和最短路相等,更新最短路的计数。
3、如果和次短路相等,更新次短路的方法数。
4、如果比次短路短,更新次短路。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define maxn 1010
#define maxm 10010
using namespace std;
const int INF = 9999999;
int s,f,n,m,cnt,ans,head[maxn];
struct node
{
int to,val,next;
}edge[maxm*2];
int dis[maxn][2],c[maxn][2]; //c[i][0]表示到点i的最短路的方法数,c[i][1]表示到点i的次短路的方法数
bool vis[maxn][2]; //dis[i][0]表示到点i的最短路,dis[i][1]表示到点i的次短路
void add(int x,int y,int z)
{
edge[cnt].to = y;
edge[cnt].val = z;
edge[cnt].next = head[x];
head[x] = cnt++;
}
void dij()
{
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
dis[i][0] = INF;
dis[i][1] = INF;
}
dis[s][0] = 0;
c[s][0] = 1;
for(int i=0;i<2*n-1;i++)
{
int tmp = INF,tx = -1,flag;
for(int j=1;j<=n;j++) //找新的最短路和次短路
{
if(!vis[j][0] && dis[j][0]<tmp)
{
tmp = dis[j][0];
tx = j;
flag = 0;
}
else if(!vis[j][1] && dis[j][1]<tmp)
{
tmp = dis[j][1];
tx = j;
flag = 1;
}
}
if(tx == -1) break; //如果新的最短路和次短路都不存在 退出循环
vis[tx][flag] = true;
for(int j=head[tx];j!=-1;j=edge[j].next) //更新和tx相连的边
{
int op = edge[j].to,w = edge[j].val;
if(tmp+w<dis[op][0]) //比最短路短,更新最短路和次短路
{
dis[op][1]=dis[op][0];
c[op][1] = c[op][0];
dis[op][0] = tmp+w;
c[op][0] = c[tx][flag];
}
else if(tmp+w==dis[op][0]) //等于最短路,更新最短路计数
c[op][0]+=c[tx][flag];
else if(tmp+w==dis[op][1]) //等于次短路,更新次短路计数
c[op][1]+=c[tx][flag];
else if(tmp+w<dis[op][1]) //小于次短路,更新最短路
{
dis[op][1] = tmp+w;
c[op][1] = c[tx][flag];
}
}
}
if(dis[f][1]==dis[f][0]+1)
c[f][0]+=c[f][1];
printf("%d\n",c[f][0]);
}
int main()
{
int T,a,b,c;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
cnt = 0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
scanf("%d%d",&s,&f);
dij();
}
return 0;
}