题目:http://acm.hdu.edu.cn/showproblem.php?pid=1688
题意:在给定有向图中查找最短路与次短路,如果(最短路+1==次短路)则输出(最短路条数+次短路条数),否则只输出最短路条数。
思路:在最短路的松弛操作上做些判断和记录即可,具体看代码吧(有注释)。
#include<iostream> #include<cstdio> #include<queue> #include<string> #include<string.h> #include<map> #include<vector> #include<algorithm> #include<cmath> #include<iterator> #define mem(a,b) memset(a,b,sizeof(a)) #define MOD 100000007 #define LL long long #define INF 0x3f3f3f3f const double pi = acos(-1.0); const int Maxn=50000; using namespace std; inline int scan() { int x=0,c=1; char ch=' '; while((ch>'9'||ch<'0')&&ch!='-')ch=getchar(); while(ch=='-')c*=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar(); return x*c; } int tol; int head[1000*2]; /*******************前向星存边**************************/ struct edge{ int to,next,w; }e[10000*2]; void add(int start,int ed,int w){ e[tol].to=ed; e[tol].w=w; e[tol].next=head[start]; head[start]=tol++; } /******************优先队列优化 **************************/ struct node{ int start; int w,p; node(int start,int w,int p):start(start),w(w),p(p){} friend bool operator < (node a,node b){ return a.w>b.w; } }; priority_queue<node>Q; int cnt[2][1010]; int dis[2][1010]; bool vis[2][1010]; void dij(int start,int ed){ dis[0][start]=0;//最短路的起点距离初始化为0 cnt[0][start]=1;//最短路因为一定会有一条,所以更新为一 Q.push(node(start,0,0)); while(!Q.empty()){ node n2=Q.top(); Q.pop(); int p=n2.p; int s=n2.start; if(vis[p][s]) continue;//如果该状态下的以s为起点已经松弛过就不要再进行操作了,会影响结果 vis[p][s]=true; for(int i=head[s];i!=-1;i=e[i].next){ int to=e[i].to; int w=e[i].w; if(dis[0][to]>dis[p][s]+w){//如果这条边会使从s到to变短,则更新s到to的最短路与次短路以及他们的条数 dis[1][to]=dis[0][to];//原先的最短路变成了次短路 dis[0][to]=dis[p][s]+w;//更新最短路 cnt[1][to]=cnt[0][to];//原先最短路条数变成次短路条数 cnt[0][to]=cnt[p][s];//更新最短路条数 Q.push(node(to,dis[0][to],0));//用这个s->to当前最短路去更新其他的路 Q.push(node(to,dis[1][to],1));//同上 }else if(dis[0][to]==dis[p][s]+w){//这条路径等于当前s->to最短路,则s->to最短路条数增加即可 cnt[0][to]+=cnt[p][s]; }else if(dis[1][to]>dis[p][s]+w){//当前路径的路径长度大于最短路但是小于次短路//更新次短路即可 dis[1][to]=dis[p][s]+w; cnt[1][to]=cnt[p][s]; Q.push(node(to,dis[1][to],1)); }else if(dis[1][to]==dis[p][s]+w){//同上 cnt[1][to]+=cnt[p][s]; } } } } int n,m; /********************************初始化*******************************/ void clear(){ tol=0; for(int i=0;i<=n;i++){ dis[0][i]=dis[1][i]=INF*2; } mem(head,-1); mem(cnt,0); mem(vis,false); mem(e,0); while(!Q.empty()) Q.pop(); } /*************************************main函数*****************************/ int main(){ std::ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int start,ed,w; cin>>n>>m; clear(); for(int i=0;i<m;i++){ cin>>start>>ed>>w; add(start,ed,w); } int s,f; cin>>s>>f; dij(s,f); // cout<<dis[0][f]<<" "<<dis[1][f]<<endl; // cout<<cnt[0][f]<<" "<<cnt[1][f]<<endl; int ans=cnt[0][f]; if(dis[0][f]+1==dis[1][f]){ ans+=cnt[1][f]; } cout<<ans<<endl; } return 0; }