POJ-3463-Sightseeing
题意:找出最短路和比最短路大一个单位的路的条数
分析:使用K短路算法会超内存,因此看完题解,要使dij变形解决问题
记录最短路和次短路,和最短路的条数和次短路的条数。
dij松弛的条件改变下,有四种情况
1.比最短路短2.等于最短路3.长与最短路但短于次短路4.等于次短路
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define MAXN 1005 #define MAXM 10050 #define INF 1000000000 struct eee{ int v,w,next; eee(){}; eee(int v,int w):v(v),w(w){}; }edge[MAXM]; struct node{ int v,c; int kind;//0最短路,1次短路 node(){}; node(int v,int c,int kind):v(v),c(c),kind(kind){}; bool operator <(const node a)const{ return c>a.c; } }; int m_d[MAXN],s_d[MAXN],m_ans[MAXN],s_ans[MAXN]; int first[MAXN]; bool vis[MAXN][2]; int n,m,e,st,en; priority_queue<node>q; void init(int n){ memset(first,-1,sizeof(first)); for(int i=0;i<=n;i++){ m_d[i]=s_d[i]=INF; m_ans[i]=s_ans[i]=0; vis[i][0]=vis[i][1]=0; } e=0; } void add(int u,int v,int w){ edge[e]=eee(v,w); edge[e].next=first[u]; first[u]=e++; } void dij(int st){ while(!q.empty())q.pop(); m_d[st]=0; m_ans[st]=1; node a=node(st,0,0); q.push(a); while(!q.empty()){ node cur=q.top(); q.pop(); if(vis[cur.v][cur.kind])continue; vis[cur.v][cur.kind]=1; int u=cur.v; for(int i=first[u];i!=-1;i=edge[i].next){ int temp_len=cur.c+edge[i].w; int v=edge[i].v; if(temp_len<m_d[v]){//比最短路小 s_d[v]=m_d[v]; s_ans[v]=m_ans[v]; a.c=s_d[v]; a.v=v; a.kind=1; q.push(a); m_d[v]=temp_len; m_ans[v]=m_ans[u]; a.c=temp_len; a.v=v; a.kind=0; q.push(a); } else if(temp_len==m_d[v]){//等于最短路 m_ans[v]=m_ans[v]+m_ans[u]; } else if(temp_len<s_d[v]){//小于次短路 s_d[v]=temp_len; if(cur.kind){ s_ans[v]=s_ans[u]; } else s_ans[v]=m_ans[u]; a.c=temp_len; a.v=v; a.kind=1; q.push(a); } else if(temp_len==s_d[v]){//等于次短路 if(cur.kind) s_ans[v]+=s_ans[u]; else s_ans[v]+=m_ans[u]; } } } } int main() { int cas; scanf("%d",&cas); while(cas--){ scanf("%d%d",&n,&m); init(n); int a,b,c; for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); } scanf("%d%d",&st,&en); dij(st); if(s_d[en]==m_d[en]+1) printf("%d\n",s_ans[en]+m_ans[en]); else printf("%d\n",m_ans[en]); } return 0; }