题意:旅行团每天固定的从S地出发到达T地,为了省油要求尽量走最短路径或比最短路径长1单位距离的路径,求满足条件的路径条数
这是一次对dijstra的深刻理解 ,好吧......不会做,参考大神思路
因为有重边,所以不能使用邻接矩阵(真的不是因为存不下.....),然后为了减少代码复杂度,使用了链式前向星
struct Edge{
int v, next, w;
}Graph[maxn*maxn];//跟大神学的,本题采用链式前向星
void add_E(int u, int v, int w){ //A is u ,B is v
Graph[e_cnt].v=v;
Graph[e_cnt].next=adj[u];
Graph[e_cnt].w=w;
adj[u]=e_cnt++;
}
上面是链式前向星的数据结构,存边,v是一条边的终点,next是上一条邻边,注意是起始点相同;需要一个adj[]数组来保存最后一条和u结点相连的边的编号,这样可以用链来访问所有的边
然后就是二维dijstra ,求出最短路和次短路,最后比较一下次短路是否比最短路多1即可;
#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <limits>
#include <vector>
#include <bitset>
#include <string>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <string.h>
#include <iostream>
#include <algorithm>
#define Si set<int>
#define LL long long
#define pb push_back
#define PS printf(" ")
#define Vi vector<int>
#define LN printf("\n")
#define lson l,m,rt << 1
#define rson m+1,r,rt<<1|1
#define SD(a) scanf("%d",&a)
#define PD(a) printf("%d",a)
#define SET(a,b) memset(a,b,sizeof(a))
#define FF(i,a) for(int i(0);i<(a);i++)
#define FD(i,a) for(int i(a);i>=(1);i--)
#define FOR(i,a,b) for(int i(a);i<=(b);i++)
#define FOD(i,a,b) for(int i(a);i>=(b);i--)
#define readf freopen("input.txt","r",stdin)
#define writef freopen("output.txt","w",stdout)
const int maxn = 1005;
const int INF = 0x3fffffff;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const double pi = acos(-1.0);
using namespace std;
int N,M;// vertex num , edge num;
bool vis[maxn][2];// visit flag
int e_cnt,adj[maxn],dis[maxn][2],cnt[maxn][2];
struct Edge{
int v, next, w;
}Graph[maxn*maxn];//跟大神学的,本题采用链式前向星
void add_E(int u, int v, int w){ //A is u ,B is v
Graph[e_cnt].v=v;
Graph[e_cnt].next=adj[u];
Graph[e_cnt].w=w;
adj[u]=e_cnt++;
}
void dijstra(int S,int F){
SET(vis,false);
SET(cnt,0);
FOR(i,1,N) dis[i][0]=dis[i][1]=INF;
cnt[S][0]=1;
dis[S][0]=0;
int k,tmp,flag;
FF(i,2*N){
tmp=INF;
FOR(j,1,N){
if(!vis[j][0] && dis[j][0]<tmp){
tmp=dis[j][0];
flag=0;
k=j;
}else if(!vis[j][1] && dis[j][1]<tmp){
tmp=dis[j][1];
flag=1;
k=j;
}
}
//此时 tmp 是 dis[j][0] 和 dis[j][1] 当中最短的
if(tmp==INF) break;
vis[k][flag]=true;
int w,v;
for(int j=adj[k];j;j=Graph[j].next){
w=Graph[j].w;
v=Graph[j].v;
if(dis[v][0] > tmp+w ){
//此时最短路变为次短路
dis[v][1]=dis[v][0];
cnt[v][1]=cnt[v][0];
//新的最短路是tmp+w
dis[v][0]=tmp+w;
cnt[v][0]=cnt[k][flag];
}else if(dis[v][0]== tmp+w){
cnt[v][0] += cnt[k][flag];
}else if(dis[v][1] > tmp+w){
dis[v][1]=tmp+w;
cnt[v][1]=cnt[k][flag];
}else if(dis[v][1] == tmp+w){
cnt[v][1] += cnt[k][flag];
}
}
}
int ans=cnt[F][0];
if(dis[F][0]+1==dis[F][1]){
ans+=cnt[F][1];
}
PD(ans);LN;
}
int main()
{
int cas, S, F;
SD(cas);
while(cas--){
SD(N);SD(M);
SET(adj,-1);
e_cnt=1;
FOR(i,1,M){
int A,B,L;
SD(A);SD(B);SD(L);
add_E(A,B,L);
}
SD(S);SD(F);
dijstra(S,F);
}
return 0;
}