codecomb 2090【最小乘积路】

来源:互联网 发布:ubuntu和优麒麟哪个好 编辑:程序博客网 时间:2024/06/05 16:52

题目描述

给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。

输入格式

第一行读入两个整数n,m,表示共n个点m条边。

接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。

输出格式

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此输出它模9987的余数即可。

样例数据 1

输入  [复制]

3 3 
1 2 3 
2 3 3 
1 3 10

输出

9

备注

对于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 9987using 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);}

0 0
原创粉丝点击