洛谷P1608路径统计

前言

关于本题,我由于被坑了一晚上...所以甚至发了个讨论版(点击查看)

由于SPFA多次入队的特殊性,导致需要一些特殊操作(本题类似P1144最短路计数,但那个题不进行spfa特殊操作能过)

更改一处:此处对上文进行更改,由于P1144边权都为1,所以不存在多次入队的情况,所以实际上没有问题,是我考虑不周!

本题坑点(做法):

  • 去重边(读入时)
  • dp数组每次清0,保证不会重复计算路径数(若用dijk,则没这个问题),不过这样只能保证dp[n]的正确性,其余的dp数组最后都为0了
  • 只要dp数组被更改过就要入队

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=2005;
  4 const int maxm=2e6+10;
  5 const int mod =100003;
  6 int head[maxm],dis[maxn],vis[maxn],dp[maxn];
  7 int cnt;
  8 /*
  9 #define pr pair<int,int>
 10 #define mp make_pair
 11 priority_queue<pr,vector<pr>,greater<pr> > q;
 12 */
 13 int v[maxn][maxn];
 14 int n,m;
 15 queue<int> q;
 16 struct edge
 17 {
 18     int to,nxt,w;
 19 }a[maxm];
 20 void add(int x,int y,int w)
 21 {
 22     a[++cnt].nxt=head[x];
 23     head[x]=cnt;
 24     a[cnt].to=y;
 25     a[cnt].w=w;
 26 }
 27 bool flag;
 28 void SPFA()
 29 {
 30     memset(dis,0x3f,sizeof(dis));
 31 //    memset(vis,0,sizeof(vis));//注意清空 
 32 //    for(int i=1;i<=n;i++)
 33 //        dis[i]=0x7fffffff;
 34     dis[1]=0;
 35     dp[1]=1;
 36     vis[1]=1;
 37     q.push(1);
 38     while(!q.empty())
 39     {
 40         int u = q.front();
 41         q.pop();
 42         vis[u]=0;
 43         if(u==n) {flag=1;continue;}
 44         for(int i=head[u];i;i=a[i].nxt)
 45         {
 46             int v=a[i].to;
 47             if(dis[v]>dis[u]+a[i].w)
 48             {
 49                 dis[v]=dis[u]+a[i].w;
 50                 dp[v]=dp[u];
 51             //    if(!vis[v]) {q.push(v);vis[v]=1;}
 52             }
 53             else if(dis[v]==dis[u]+a[i].w)
 54             {
 55                 dp[v]+=dp[u];
 56             }
 57             if(dp[v]&&!vis[v]) {q.push(v);vis[v]=1;}
 58         }
 59         dp[u]=0;
 60     }
 61 }
 62 int main()
 63 {
 64     scanf("%d%d",&n,&m);
 65     int x,y,w;
 66     for(int i=1;i<=m;i++)
 67     {
 68         scanf("%d%d%d",&x,&y,&w);
 69         if(v[x][y]==0)
 70         {            
 71             add(x,y,w);
 72             v[x][y]=w;
 73             
 74         }
 75         else if(v[x][y]>w)
 76         {
 77             int j;
 78             for (j=head[x];j&&a[j].to!=y;j=a[j].nxt) ;
 79             a[j].w=w;
 80             v[x][y]=w;
 81         }
 82 
 83     }
 84     SPFA();
 85     if(!flag) printf("No answer");
 86     else
 87     {
 88         printf("%d %d\n",dis[n],dp[n]);
 89     }
 90 //    for(int i=1;i<=n;i++)
 91 //        printf("%d ",dp[i]);
 92 /*
 93 5 5
 94 1 2 1
 95 2 3 1
 96 3 4 1
 97 4 5 1
 98 1 4 3
 99 输出:4 2 
100 */
101     return 0;
102 }

吐槽

关于SPFA:它死了!

posted @ 2021-02-04 16:13  conprour  阅读(135)  评论(0编辑  收藏  举报