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 }
这样的一份代码,在
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 }