题目描述
给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。
输入格式
第一行读入两个整数n,m,表示共n个点m条边。
接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。
输出格式
输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此输出它模9987的余数即可。
样例数据 1
备注
对于20%的数据,n<=10。
对于100%的数据,n<=1000,m<=1000000。边权不超过10000。
这题把最短路的dist改成乘起来的形式,然后还要取模,看起来裸的最短路会爆
实际上对边权取个log之后,dist就变成相加了
这样没法保证路径上取模的正确性,所以要先搞出最短路的路径然后再算出ans
我只能说这题卡spfa卡的不错……死都是90
就是不写dij你咬我啊
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 2147483647
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
#define md 100007
#define mod 9987
using namespace std;
struct edge{
int from,to,next,v;
double fv;
}e[800010],us[800010];
struct hashing{
int fr,to,next,rnk;
}hash[1000000];
int he[md];
int head[10010];
int n,m,cnt,cnt2,t,w,ans;
int q[100010];
double dist[100010];
int fa[100010];
int fav[100010];
bool mrk[100010];
inline int searc(int fr,int to)
{
int now=((fr+213)*(to+250))%md;
for (int i=he[now];i;i=hash[i].next)
if (hash[i].fr==fr&&hash[i].to==to)return hash[i].rnk;
return -1;
}
inline void ins_ha(int fr,int to,int rnk)
{
int now=((fr+213)*(to+250))%md;
hash[++cnt2].fr=fr;
hash[cnt2].to=to;
hash[cnt2].rnk=rnk;
hash[cnt2].next=he[now];
he[now]=cnt;
}
inline void ins_ed(int u,int v,int w)
{
us[++cnt].to=v;
us[cnt].from=u;
us[cnt].v=w;
us[cnt].next=head[u];
head[u]=cnt;
}
inline void ins_e(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].from=u;
e[cnt].v=w;
e[cnt].next=head[u];
head[u]=cnt;
}
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void spfa(int S)
{
for (int i=1;i<=n;i++)mrk[i]=0;
for (int i=1;i<=n;i++)dist[i]=inf;
memset(q,0,sizeof(q));
q[0]=S;mrk[S]=1;dist[S]=0;
t=0;w=0;
do
{
int now=q[t];
t=(t+1)%md;
for (int i=head[now];i;i=e[i].next)
if (dist[e[i].to]>dist[now]+e[i].fv)
{
dist[e[i].to]=dist[now]+e[i].fv;
fa[e[i].to]=now;
fav[e[i].to]=e[i].v;
if (!mrk[e[i].to])
{
mrk[e[i].to]=1;
if (dist[q[t]]>dist[e[i].to])
{
t=(t-1+md)%md;
q[t]=e[i].to;
}
else
{
w=(w+1)%md;
q[w]=e[i].to;
}
}
}
mrk[now]=0;
}
while (t!=w);
}
int main()
{
n=read();m=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
int fnd=searc(x,y);
if (fnd==-1)
{
ins_ed(x,y,z);
ins_ha(x,y,cnt);
}else
{
us[fnd].v=min(us[fnd].v,z);
}
}
memset(head,0,sizeof(head));
int sum=cnt;cnt=0;
for (int i=1;i<=sum;i++)
{
ins_e(us[i].from,us[i].to,us[i].v);
}
for (int i=1;i<=cnt;i++)
e[i].fv=log(e[i].v);
spfa(1);
int s=n,ans=1;
while (s!=1)
{
ans=(ans*fav[s])%mod;
s=fa[s];
}
printf("%d\n",ans);
}