模拟赛 最小乘积路

来源:互联网 发布:史上最奇葩的淘宝差评 编辑:程序博客网 时间:2024/05/16 14:20

题目描述

给定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。

题解

一道很简单的最短路,取个对数并记录路径即可。

方案一:spfa+SLF优化,话说感觉spfa好写。

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#define ll long long#define MAXN 1000002#define mod 9987#define inf 1<<30using namespace std;int n,m,zz,head[1002];struct bian {int frm,to,nx,v;double c;} e[MAXN];double dis[1002];int pd[1002],from[1002],q[1002];void insert(int x,int y,int z){zz++; e[zz].frm=x; e[zz].to=y;e[zz].v=z; e[zz].c=log(z);e[zz].nx=head[x]; head[x]=zz;}void init(){scanf("%d%d",&n,&m);int i,x,y,z;for(i=1;i<=m;i++)   {scanf("%d%d%d",&x,&y,&z);    insert(x,y,z);   }}void spfa(){int i,t=0,w=1,x,p;for(i=1;i<=n;i++) dis[i]=inf;q[t]=1; dis[1]=0; pd[1]=1;while(t!=w)   {x=q[t]; t=(t+1)%1000;    for(i=head[x];i;i=e[i].nx)   {p=e[i].to;    if(dis[p]>dis[x]+e[i].c)       {dis[p]=dis[x]+e[i].c;        from[p]=i;    if(!pd[p])       {if(dis[p]<=dis[q[t]])       {t=(t+1000-1)%1000; q[t]=p; pd[p]=1;}    else       {q[w]=p; pd[p]=1; w=(w+1)%1000;}   }   }   }pd[x]=0;   }i=from[n];ll ans=1;while(i!=0)   {ans=(ans*e[i].v)%mod;    i=from[e[i].frm];   }printf("%lld\n",ans);}int main(){init(); spfa();return 0;}

方案二:spfa+堆,话说只是因为感觉这种算法会快一点点,好像实际上也没有快多少,有些点更慢了。

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#define ll long long#define MAXN 1000002#define mod 9987#define inf 1<<30using namespace std;int n,m,zz,head[1002];struct bian {int frm,to,nx,v;double c;} e[MAXN];double dis[1002];int pd[1002],from[1002],q[1002],size;void insert(int x,int y,int z){zz++; e[zz].frm=x; e[zz].to=y;e[zz].v=z; e[zz].c=log(z);e[zz].nx=head[x]; head[x]=zz;}void init(){scanf("%d%d",&n,&m);int i,x,y,z;for(i=1;i<=m;i++)   {scanf("%d%d%d",&x,&y,&z);    insert(x,y,z);   }}void heapfy(int w){int l=w<<1,r=l+1,minw=w;if(l<=size&&dis[q[l]]<dis[q[w]]) minw=l;if(r<=size&&dis[q[r]]<dis[q[minw]]) minw=r;if(minw!=w)   {swap(q[w],q[minw]); heapfy(minw);}}void del(){q[1]=q[size]; size--;if(size) heapfy(1);}void weih(int w){while(w>1)   {int i=w>>1;    if(dis[q[w]]<dis[q[i]]) swap(q[w],q[i]);    w=w>>1;   }}void spfa(){int i,x,p;for(i=1;i<=n;i++) dis[i]=inf;q[1]=1; dis[1]=0; pd[1]=1; size=1;while(size>0)   {x=q[1]; del();    for(i=head[x];i;i=e[i].nx)   {p=e[i].to;    if(dis[p]>dis[x]+e[i].c)       {dis[p]=dis[x]+e[i].c;        from[p]=i;    if(!pd[p])       {q[++size]=p; pd[p]=1; weih(size);}   }   }pd[x]=0;   }i=from[n];ll ans=1;while(i!=0)   {ans=(ans*e[i].v)%mod;    i=from[e[i].frm];   }printf("%lld\n",ans);}int main(){init(); spfa();return 0;}

方案三:dijkstra+堆,话说我不会用STL库的东西(太难记了),所以我的代码是手写堆,很长。比以上两种方法快了不少。

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<cmath>#include<algorithm>#define ll long long#define mod 9987using namespace std;int n,m,zz,head[1002];struct bian{int frm,to,nx,v; double c;} e[1000002];struct dui{double d;int w;} q[10002];int pd[1002],size,from[1002];double dis[1002];//-----------------------------------------------------------------------------int read(){int 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;}void insert(int x,int y,int z){zz++; e[zz].to=y; e[zz].frm=x;e[zz].v=z; e[zz].c=log(z);e[zz].nx=head[x]; head[x]=zz;}void init(){n=read(); m=read();int i,x,y,z;for(i=1;i<=m;i++)   {x=read(); y=read(); z=read();    insert(x,y,z);   }}void heapfy(int x){int l=x<<1,r=l+1,minx=x;if(l<=size&&q[l].d<q[x].d) minx=l;if(r<=size&&q[r].d<q[minx].d) minx=r;if(minx!=x)   {swap(q[minx],q[x]); heapfy(minx);}}void del(){q[1]=q[size]; size--;if(size) heapfy(1);}void weih(int x){if(x<=1) return;int i=x>>1;if(q[i].d>q[x].d) swap(q[i],q[x]);weih(i);}void dijkstra(){int i,x,p;for(i=1;i<=n;i++) dis[i]=1e10;size=1; q[1].d=log(1); q[1].w=1; dis[1]=0;while(size)   {x=q[1].w; del();    if(pd[x]) continue;    pd[x]=1;    for(i=head[x];i;i=e[i].nx)       {p=e[i].to;if(dis[p]>dis[x]+e[i].c)   {dis[p]=dis[x]+e[i].c;from[p]=i;    size++; q[size].d=dis[p]; q[size].w=p; weih(size);   }   }   }ll ans=1;for(i=from[n];i;i=from[e[i].frm])   ans=(ans*e[i].v)%mod;printf("%lld\n",ans);}int main(){init(); dijkstra();return 0;}

0 0