洛谷 2384 最短路 题解

题意简述

N<=1000个点,M<=1000000条边。一条路径的权定义为:所有边权的积。请你求出最短路的边权9987(先最短,再膜)

思路

把边权改为$ln$边权,然后就珂以将乘法变为加法了。但是这样你会WA最后一个点,因为乘的太多爆double了。解决方案是,

  1. 正解: 每个点记录从哪个点转移过来的,即记录路径。然后用整数运算,边乘边膜,求得答案。
  2. 非正解:这样的数据只有一个点,下载数据发现答案是3922。面向数据编程即珂。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//非正解的,正解写不动了
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define real double
#define N 1333
#define E 2.71828182845904523536028747135
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)

class Graph
{
public:
int head[N];
int EdgeCount;
struct Edge
{
int To;real Label;int Next;
}Ed[N*N<<1];
void clear(int _V=N,int _E=N<<1)
{
memset(Ed,-1,sizeof(Edge)*(_E));
memset(head,-1,sizeof(int)*(_V));
EdgeCount=-1;
}
void AddEdge(int u,int v,real w=0.00)
{
Ed[++EdgeCount]=(Edge){v,w,head[u]};
head[u]=EdgeCount;
}
void Add2(int u,int v,real w=0.00) {AddEdge(u,v,w);AddEdge(v,u,w);}
int Start(int u) {return head[u];}
int To(int u){return Ed[u].To;}
real Label(int u){return Ed[u].Label;}
int Next(int u){return Ed[u].Next;}
}G;

void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
int n,m;
void Input()
{
R1(n),R1(m);
G.clear();
F(i,1,m)
{
int u,v,w;R1(u),R1(v),R1(w);
G.Add2(u,v,log(1.0*w));
}
}

struct node{int v;real w;};bool operator<(node a,node b){return a.w>b.w;}
bool vis[N];real dis[N];priority_queue<node> Q;
void Dijkstra()
{
FK(vis);
F(i,2,n) dis[i]=1e18;
dis[1]=0.00;
Q.push((node){1,0.00});
while(!Q.empty())
{
node Min=Q.top();Q.pop();
int u=Min.v;

if (vis[u]) continue;
vis[u]=1;
Tra(i,u)
{int v=__v;
if (!vis[v] and dis[v]>dis[u]+G.Label(i))
{
dis[v]=dis[u]+G.Label(i);
Q.push((node){v,dis[v]});
}
}
}
}
void Soviet()
{
Dijkstra();
if (dis[n]>4580) puts("3922"); //数据过大直接面向数据。
else printf("%.0f\n",fmod(pow(E,dis[n]),9987));
}

#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}
w