P2384 最短路 乘法最短路 乘法转加法

题意:求从 11 到 nn 的路径中边权之积最小的简单路径。

思路:题目中给出最大边权为1e4;

   我们按模板的写法,把加法改成乘法来做这道题。

   代码如下:

   

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e3+10;
 5 const int maxm=1e6+10;
 6 const ll mod=9987;
 7 const int inf=0x3f3f3f3f;
 8 struct node
 9 {
10     int v;
11     ll w;
12     int nxt;
13 }G[maxm]; int head[maxm]; int num;
14 void add(int u,int v,ll w)
15 {
16     G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num;
17 }
18 int vis[maxn];
19 ll dis[maxn];
20 int n,m;
21 void SPFA()
22 {
23     queue<int>q;
24     for(int i=1;i<=n;i++)
25         dis[i]=mod;
26     memset(vis,0,sizeof(vis));
27     q.push(1);
28     vis[1]=1;
29     dis[1]=1;
30     while(!q.empty()){
31         int u=q.front();
32         q.pop();
33         vis[u]=0;
34         for(int i=head[u];i;i=G[i].nxt){
35             int v=G[i].v;ll w=G[i].w;
36             ll tmp=dis[u]*w%mod;
37             if(dis[v]>tmp){
38                 dis[v]=tmp;
39                 if(!vis[v]){
40                     vis[v]=1;
41                     q.push(v);
42                 }
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;ll w;
52         scanf("%d%d%lld",&u,&v,&w);
53         add(u,v,w);
54     }
55     SPFA();
56     printf("%lld\n",dis[n]);
57 }
View Code

这种做法是错误的,老实说这种做法能水到90分也是醉了。。。

这种做法错在哪呢?假如没有取模操作并且不涉及大数的话,这种做法倒是对的

但是有了取模之后,会导致不应该作为最短路路径的一些路径因为取模操作涉及进来;

正确做法应该是运用log操作,把乘法变成加法

 

 代码如下:

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

 

posted @ 2020-04-21 16:12  古比  阅读(247)  评论(0编辑  收藏  举报