poj 3463 Sightseeing

    技术2025-05-19  4

    求最短路和比最短路大1的路径数目

     

    其实就是求最短路和次短路的数目,如果次短路比最短路小1,则两者相加

     

    开二维数组dis[N][2]和cnt[N][2],dis[i][0]表示到i点的最短距离,dis[i][1]表示到i点的次短距离,cnt[i][0]和cnt[i][1]分别表示到i点的最短路和次短路的数目

     

    利用dijkstra算法,通过2n-1次就可计算出

     

    更新情况分为4种:

    1.比最短路还小,则它成为新的最短路,原来的最短路成为次短路

    2.和最短路一样大,则增加最短路的数目

    3.比次短路小,则它成为新的次短路

    4.和次短路一样样,则增加次短路的数目

     

    代码:

    #include<iostream> #include<queue> using namespace std; const int MAX=1005; const int inf=1<<30; struct node { int v,c,next; }g[MAX*MAX]; int dis[MAX][2],vis[MAX][2],adj[MAX],cnt[MAX][2]; int n,m,s,t,e; void add(int u,int v,int c) { g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++; } int dijkstra() { int i,j,k,u,v,w,minn,flag; memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); cnt[s][0]=1; for(i=1;i<=n;i++) { dis[i][0]=dis[i][1]=inf; } dis[s][0]=0; for(i=1;i<2*n;i++) { minn=inf; for(j=1;j<=n;j++) { if(!vis[j][0]&&dis[j][0]<minn)//得到新的最短路 { flag=0; u=j; minn=dis[j][0]; } else if(!vis[j][1]&&dis[j][1]<minn)//得到新的次短路 { flag=1; u=j; minn=dis[j][1]; } } if(minn==inf) break; vis[u][flag]=1; for(k=adj[u];k!=-1;k=g[k].next) { v=g[k].v; w=g[k].c; if(dis[v][0]>minn+w)//比最短路还小 { dis[v][1]=dis[v][0]; cnt[v][1]=cnt[v][0]; dis[v][0]=minn+w; cnt[v][0]=cnt[u][flag]; } else if(dis[v][0]==minn+w)//与最短路一样 { cnt[v][0]+=cnt[u][flag]; } else if(dis[v][1]>minn+w)//比次短路小 { dis[v][1]=minn+w; cnt[v][1]=cnt[u][flag]; } else if(dis[v][1]==minn+w)//与次短路一样 { cnt[v][1]+=cnt[u][flag]; } } } //cout<<dis[t][0]<<" "<<dis[t][1]<<endl; if(dis[t][1]==dis[t][0]+1) cnt[t][0]+=cnt[t][1]; return cnt[t][0]; } int main() { int i,j,w,T; scanf("%d",&T); while(T--) { e=0; memset(adj,-1,sizeof(adj)); scanf("%d%d",&n,&m); while(m--) { scanf("%d%d%d",&i,&j,&w); add(i,j,w); } scanf("%d%d",&s,&t); printf("%d/n",dijkstra()); } return 0; } 

    最新回复(0)