POJ 3463 Sightseeing

 

 

 

 

 

题意:给你一个图和起始两点,要求求出两点之间最短路和比最短路长一个单位的路径条数总和。

思路分析:看到长一个单位想到次短路,次短路要用到A*,但是发现估价函数好像不会写(其实是可以的,但蒟蒻不会)。于是我们采取dijkstra算法来解决这道问题,由于要求求出两条路径,于是dis数组开成dis[N][2],分别表示最短路长度和次短路长度,sum数组表示从起点到当前点的路径条数,那么我们更新时就会有以下四种情况: 

 1.若找到比当前最短路更短的路径时,这条路成为最短路,原来最短路成为次短路。

 2.若当前长度和当前最短路长度相等时,sum累加一下。

 3.若当前路长度在最短,次短之间,这条路变为次短路。

 4..若当前长度和当前次短路长度相等时,sum累加一下。

之后就没有什么了,注意题目说是单向边。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int N=1e6+10;
 7 struct Node{
 8     int next,to,dis;
 9 }edge[N];
10 int Head[N],tot;
11 void Add(int x,int y,int z){
12     edge[++tot].to=y;
13     edge[tot].next=Head[x];
14     edge[tot].dis=z;
15     Head[x]=tot;
16 }
17 int dis[N][2],sum[N][2];
18 struct Edge{
19     int num,dis,t;
20     Edge(int x,int y,int z){
21         num=x;dis=y;t=z;
22     }
23     bool operator < (const Edge& a)const{
24         return a.dis<dis;
25     }
26 };
27 priority_queue<Edge>q;
28 int vis[N][2];
29 void dijkstra(int x){
30     memset(dis,0x3f,sizeof(dis));
31     memset(sum,0,sizeof(sum));
32     memset(vis,0,sizeof(vis));
33     dis[x][1]=dis[x][0]=0;
34     sum[x][0]=1;
35     q.push(Edge(x,0,0));
36     while(!q.empty()){
37         Edge top=q.top();q.pop();
38         if(vis[top.num][top.t]) continue;
39         vis[top.num][top.t]=1;
40         int u=top.num,t=top.t;
41         for(int i=Head[u];i;i=edge[i].next){
42             int v=edge[i].to;
43             if(dis[v][0]>dis[u][t]+edge[i].dis){
44                 dis[v][1]=dis[v][0];sum[v][1]=sum[v][0];
45                 dis[v][0]=dis[u][t]+edge[i].dis;
46                 sum[v][0]=sum[u][t];
47                 q.push(Edge(v,dis[v][0],0));
48                 q.push(Edge(v,dis[v][1],1));
49             }
50             else if(dis[v][0]==dis[u][t]+edge[i].dis){
51                 sum[v][0]+=sum[u][t];
52             }
53             else if(dis[v][1]>dis[u][t]+edge[i].dis){
54                 dis[v][1]=dis[u][t]+edge[i].dis;
55                 sum[v][1]=sum[u][t];
56                 q.push(Edge(v,dis[v][1],1));
57             }
58             else if(dis[v][1]==dis[u][t]+edge[i].dis){
59                 sum[v][1]+=sum[u][t];
60             }
61         } 
62     }
63 }
64 int main(){
65     //freopen("a.txt","r",stdin);
66     int T;
67     scanf("%d",&T);
68     while(T--){
69         memset(Head,0,sizeof(Head));
70         memset(edge,0,sizeof(edge));
71         memset(sum,0,sizeof(sum));
72         int n,m;
73         scanf("%d%d",&n,&m);
74         for(int i=1;i<=m;++i){
75             int x,y,z;
76             scanf("%d%d%d",&x,&y,&z);
77             Add(x,y,z);
78         }
79         int x,y;
80         scanf("%d%d",&x,&y);
81         dijkstra(x);
82         int ans=sum[y][0];
83         if(dis[y][0]+1==dis[y][1]) ans+=sum[y][1];//次短路比最短路长1时累加 
84         printf("%d\n",ans);
85     }
86     return 0;
87 }
View Code

 

posted @ 2020-05-24 23:41  19502-李嘉豪  阅读(123)  评论(0编辑  收藏  举报