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 }
这种做法是错误的,老实说这种做法能水到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 }