P1608 路径统计 单向图求最短路径数

题意:单向图求最短路径数

思路:跑一遍SPFA,然后需要在原有的模板上有所修改。注释写在代码中

   首先来一份91分的代码

   

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=2e3+10;
 5 int dis[maxn];
 6 int vis[maxn];
 7 int sum[maxn];
 8 int match[maxn][maxn];
 9 struct Node
10 {
11     int v,w,nxt;
12 }G[maxn*maxn]; int head[maxn*maxn]; int num;
13 int n,m;
14 void add(int u,int v,int w)
15 {
16     G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num;
17 }
18 void SPFA()
19 {
20     memset(dis,inf,sizeof(dis));
21     memset(vis,0,sizeof(vis));
22     queue<int>q;
23     q.push(1);
24     vis[1]=1;
25     dis[1]=0;
26     sum[1]=1;
27     while(!q.empty()){
28         int u=q.front();
29         q.pop();
30         vis[u]=0;
31         for(int i=head[u];i;i=G[i].nxt){
32             int v=G[i].v,w=G[i].w;
33             if(dis[v]>dis[u]+w){
34                 dis[v]=dis[u]+w;
35                 sum[v]=sum[u];
36                 if(!vis[v]){
37                     vis[v]=1;
38                     q.push(v);
39                 }
40             }
41             else if(dis[v]==dis[u]+w){
42                 sum[v]+=sum[u];
43             }
44         }
45     }
46 }
47 int main()
48 {
49     scanf("%d%d",&n,&m);
50     for(int i=1;i<=m;i++){
51         int u,v,w;
52         scanf("%d%d%d",&u,&v,&w);
53         if(match[u][v]==0||match[u][v]>w){
54             add(u,v,w);
55             match[u][v]=w;
56         }
57     }
58     SPFA();
59     if(dis[n]==inf) printf("No answer\n");
60     else printf("%d %d\n",dis[n],sum[n]);
61     return 0;
62 }
View Code

这样的一份代码,在

5 5

1 2 1

2 3 1

3 4 1 

1 4 3 

4 5 1

这样的一个数据就过不去,演算一遍就知道了。

于是改成这样的一份代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=2e3+10;
 5 int dis[maxn];
 6 int vis[maxn];
 7 int sum[maxn];
 8 int match[maxn][maxn];
 9 struct Node
10 {
11     int v,w,nxt;
12 }G[maxn*maxn]; int head[maxn*maxn]; int num;
13 int n,m;
14 void add(int u,int v,int w)
15 {
16     G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num;
17 }
18 void SPFA()
19 {
20     memset(dis,inf,sizeof(dis));
21     memset(vis,0,sizeof(vis));
22     queue<int>q;
23     q.push(1);
24     vis[1]=1;
25     dis[1]=0;
26     sum[1]=1;        //把开始的位置定义为1
27     while(!q.empty()){
28         int u=q.front();
29         q.pop();
30         vis[u]=0;
31         if(u==n) continue;
32         for(int i=head[u];i;i=G[i].nxt){
33             int v=G[i].v,w=G[i].w;
34             if(dis[v]>dis[u]+w){   //假如遇到更新长度的情况
35                 dis[v]=dis[u]+w;   //就把父亲的长度继承给他
36                 sum[v]=sum[u];
37             }
38             else if(dis[v]==dis[u]+w){  //假如不用更新长度,但是两者长度相同
39                 sum[v]+=sum[u];   //就在原有数目上再增加父亲的数目
40             }
41             if(sum[v]&&!vis[v]){  //这就是区别于模板SPFA的一个地方
42                 vis[v]=1;         //我们在当前sum【v】有值的情况下,再入队
43                 q.push(v);        
44             }
45         }
46         sum[u]=0;                 //把这个位置的sum值清零
47     }
48 }
49 int main()
50 {
51     scanf("%d%d",&n,&m);
52     for(int i=1;i<=m;i++){
53         int u,v,w;
54         scanf("%d%d%d",&u,&v,&w);
55         if(match[u][v]==0||match[u][v]>w){
56             add(u,v,w);
57             match[u][v]=w;
58         }
59     }
60     SPFA();
61     if(dis[n]==inf) printf("No answer\n");
62     else printf("%d %d\n",dis[n],sum[n]);
63     return 0;
64 }
View Code

 

posted @ 2020-04-18 09:41  古比  阅读(286)  评论(0编辑  收藏  举报