dijkstra求最短路和次短路的求法和计算 模板
dijkstra求最短路的变形。
外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次。
算法:
1、如果比最短路短就更新最短路和次短路。
2、如果和最短路相等,更新最短路的计数。
3、如果和次短路相等,更新次短路的方法数。
4、如果比次短路短,更新次短路。
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #define maxn 1010 #define maxm 10010 using namespace std; const int INF = 9999999; int s,f,n,m,cnt,ans,head[maxn]; struct node { int to,val,next; }edge[maxm*2]; int dis[maxn][2],c[maxn][2]; //c[i][0]表示到点i的最短路的方法数,c[i][1]表示到点i的次短路的方法数 bool vis[maxn][2]; //dis[i][0]表示到点i的最短路,dis[i][1]表示到点i的次短路 void add(int x,int y,int z) { edge[cnt].to = y; edge[cnt].val = z; edge[cnt].next = head[x]; head[x] = cnt++; } void dij() { memset(c,0,sizeof(c)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { dis[i][0] = INF; dis[i][1] = INF; } dis[s][0] = 0; c[s][0] = 1; for(int i=0;i<2*n-1;i++) { int tmp = INF,tx = -1,flag; for(int j=1;j<=n;j++) //找新的最短路和次短路 { if(!vis[j][0] && dis[j][0]<tmp) { tmp = dis[j][0]; tx = j; flag = 0; } else if(!vis[j][1] && dis[j][1]<tmp) { tmp = dis[j][1]; tx = j; flag = 1; } } if(tx == -1) break; //如果新的最短路和次短路都不存在 退出循环 vis[tx][flag] = true; for(int j=head[tx];j!=-1;j=edge[j].next) //更新和tx相连的边 { int op = edge[j].to,w = edge[j].val; if(tmp+w<dis[op][0]) //比最短路短,更新最短路和次短路 { dis[op][1]=dis[op][0]; c[op][1] = c[op][0]; dis[op][0] = tmp+w; c[op][0] = c[tx][flag]; } else if(tmp+w==dis[op][0]) //等于最短路,更新最短路计数 c[op][0]+=c[tx][flag]; else if(tmp+w==dis[op][1]) //等于次短路,更新次短路计数 c[op][1]+=c[tx][flag]; else if(tmp+w<dis[op][1]) //小于次短路,更新最短路 { dis[op][1] = tmp+w; c[op][1] = c[tx][flag]; } } } if(dis[f][1]==dis[f][0]+1) c[f][0]+=c[f][1]; printf("%d\n",c[f][0]); } int main() { int T,a,b,c; scanf("%d",&T); while(T--) { memset(head,-1,sizeof(head)); cnt = 0; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); } scanf("%d%d",&s,&f); dij(); } return 0; }
poj 3463 Sightseeing (dij 求最短路和次短路并计数)
时间: 2024-10-08 07:40:08