Sightseeing(poj 3463)
题意:给出n个点m条单向边,求最短路的道路条数和比最短路大1的道路条数的和。
/* 用Dijkstra更新2*n次,来更新出所有点的最短路和次短路,顺便更新方案数。 */ #include<cstdio> #include<iostream> #include<cstring> #define N 1010 #define INF 500000000 using namespace std; int head[N],vis[N][2],dis[N][2],f[N][2],n,m,s,t; struct node{ int v,pre,t; };node e[N*10]; void add(int i,int x,int y,int z){ e[i].v=y; e[i].t=z; e[i].pre=head[x]; head[x]=i; } void Dij() { dis[s][0]=0;f[s][0]=1; for(int T=1;T<=n*2;T++){ int minn=INF,pos=0,flag; for(int i=1;i<=n;i++){ if(dis[i][0]<minn&&!vis[i][0]){ minn=dis[i][0];pos=i;flag=0; } if(dis[i][1]<minn&&!vis[i][1]){ minn=dis[i][1];pos=i;flag=1; } } if(!pos)break; vis[pos][flag]=1; for(int i=head[pos];i;i=e[i].pre){ int v=e[i].v; if(minn+e[i].t<dis[v][0]){ dis[v][1]=dis[v][0]; f[v][1]=f[v][0]; dis[v][0]=minn+e[i].t; f[v][0]=f[pos][flag]; } else if(minn+e[i].t==dis[v][0]){ f[v][0]+=f[pos][flag]; } else if(minn+e[i].t<dis[v][1]){ dis[v][1]=minn+e[i].t; f[v][1]=f[pos][flag]; } else if(minn+e[i].t==dis[v][1]){ f[v][1]+=f[pos][flag]; } } } if(dis[t][0]==dis[t][1]-1) printf("%d\n",f[t][0]+f[t][1]); else printf("%d\n",f[t][0]); } void work(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y,z;scanf("%d%d%d",&x,&y,&z); add(i,x,y,z); } scanf("%d%d",&s,&t); Dij(); } int main(){ int T;scanf("%d",&T); while(T--){ memset(dis,127/3,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f)); memset(head,0,sizeof(head)); memset(e,0,sizeof(e)); work(); } return 0; }