poj 3463 (次短路的模版)
来源:互联网 发布:淘宝效果图是啥意思 编辑:程序博客网 时间:2024/06/06 00:38
求最短路数量和和次短路与最短路长度大于1的途径数量。 原来想用第K短路把所有的前面最短的和次短(K=1,2,3,,,,)最后TLE了,不知道A*的复杂度是多少,然后的得用次短路求解,用dp[][2]数组存顶点遍历的次数,Source CodeProblem: 3463 User: 1013101127Memory: 852K Time: 516MSLanguage: G++ Result: AcceptedSource Code#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <algorithm>using namespace std;const int INF=9999999;struct node{ int v; int len; int next;}edge[10005];bool cmp(node a,node b){ return a.len<b.len;}int cnt;int head[1003];int n,m;int start;int end;void init(){ for(int i=1;i<=n;i++) head[i]=-1; cnt=0;}void insert(int u,int v,int len){ edge[cnt].v=v;edge[cnt].len=len;edge[cnt].next=head[u]; head[u]=cnt; cnt++;}int disj(int S,int E){ int i,j; int v[1002][2]; int dis[1002][2]; int dp[1002][2];//记录顶点遍历的次数,次短路的模版没有这个, memset(v,0,sizeof(v)); memset(dp,0,sizeof(dp)); for(i = 1;i <= n;i ++) dis[i][0] = dis[i][1] = INF; dis[S][0] = 0; dp[S][0] = 1; int x,flag; for(i = 1;i <= n*2;i ++) { int min_d = INF; for(j = 1;j <= n;j ++) { if(!v[j][0] && min_d > dis[j][0]) { min_d = dis[j][0]; x = j; flag = 0; } else if(!v[j][1] && min_d > dis[j][1]) { min_d = dis[j][1]; x = j; flag = 1; } } v[x][flag] = 1; if(min_d == INF) break; for(j = head[x];j != -1;j = edge[j].next) { int len = min_d + edge[j].len,y = edge[j].v; if(len < dis[y][0]) { dis[y][1] = dis[y][0]; dp[y][1] = dp[y][0]; dis[y][0] = len; dp[y][0] = dp[x][flag]; } else if(len == dis[y][0]) { dp[y][0] += dp[x][flag]; } else if(len < dis[y][1]) { dis[y][1] = len; dp[y][1] = dp[x][flag]; } else if(len == dis[y][1]) { dp[y][1] += dp[x][flag]; } } } int ans; if(dis[E][0]+1==dis[E][1])//最短路和次短路差一 ans=dp[E][0]+dp[E][1]; else ans=dp[E][0]; return ans;}int main(){ int cas; int uu,vv,L; cin>>cas; while(cas--) { cin>>n>>m; init(); for(int i=1;i<=m;i++) { cin>>uu>>vv>>L; insert(uu,vv,L); } cin>>start>>end; cout<<disj(start,end)<<endl; } return 0;}