/**//* 求s到t的最短路与次短路(这里要求只比最短路多1)的条数之和 联想到最小,次小的一种更新关系: if(x<最小)更新最小,次小 else if(==最小)更新方法数 else if(x<次小)更新次小 else if(x==次小)更新方法数
同时记录s到u最短,次短路及方法数 用一个堆每次取最小的,更新完后再入堆 还是那个原理,第一次遇到的就是最优的,然后vi标记为真 方法数注意是加法原理,不是乘法 \ -- u -- v 所以是加法原理 / */ #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std;
const int MAXN=1010; const int INF=1000000000;
bool vi[MAXN][2]; int dist[MAXN][2],cnt[MAXN][2];//0 表示最短路 1表示次短路 int G[MAXN]; int n,m,alloc;
struct Node{ int v,w,next; }nodes[MAXN*10];
struct Pos{ int v,flag; Pos(int vv,int f){v=vv,flag=f;} bool operator<(const Pos &p)const { return dist[v][flag]>dist[p.v][p.flag]; } };
void add(int a,int b,int c){ alloc++; nodes[alloc].v=b,nodes[alloc].w=c,nodes[alloc].next=G[a]; G[a]=alloc; }
int dij(int s,int t){ memset(vi,0,sizeof(vi)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) dist[i][0]=dist[i][1]=INF; priority_queue<Pos>Q; Q.push(Pos(s,0)); dist[s][0]=0;cnt[s][0]=1; while(!Q.empty()){ Pos top=Q.top();Q.pop(); int u=top.v,flag=top.flag; if(vi[u][flag])continue; vi[u][flag]=1; for(int son=G[u];son;son=nodes[son].next){ int v=nodes[son].v,w=dist[u][flag]+nodes[son].w; if(w<dist[v][0]){ if(dist[v][0]!=INF){ dist[v][1]=dist[v][0]; cnt[v][1]=cnt[v][0]; Q.push(Pos(v,1)); } dist[v][0]=w; cnt[v][0]=cnt[u][flag]; Q.push(Pos(v,0)); } else if(w==dist[v][0])cnt[v][0]+=cnt[u][flag]; else if(w<dist[v][1]){ dist[v][1]=w; cnt[v][1]=cnt[u][flag]; Q.push(Pos(v,1)); } else if(w==dist[v][1])cnt[v][1]+=cnt[u][flag]; } }
int ans=cnt[t][0]; if(dist[t][0]==dist[t][1]-1)ans+=cnt[t][1]; return ans; } int main(){ int T,a,b,c; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); memset(G,0,sizeof(G)); alloc=0; while(m--){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); } scanf("%d%d",&a,&b); printf("%d\n",dij(a,b)); } return 0; }
|