模拟赛 最小乘积路
来源:互联网 发布:史上最奇葩的淘宝差评 编辑:程序博客网 时间: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
- 模拟赛 最小乘积路
- codecomb 2090【最小乘积路】
- 最小乘积
- 最小乘积
- 最小乘积
- 最小乘积
- 最小乘积
- 最小乘积
- 最小乘积
- 最小乘积
- 2014.9.13模拟赛【数位和乘积】
- 最小向量乘积
- 最小向量乘积
- 蓝桥杯 最小乘积
- 最小乘积型
- 最小乘积(基本型)
- 最小乘积(基本型)
- csdn 最小向量乘积
- Button的高宽无故变大了!
- Linux下的多线程编程(三) 杂七杂八
- Phone重绘机制drawRect
- 跟我一起Django - 05 URL HTTP机制和视图
- 作为一个合格程序员该做的事
- 模拟赛 最小乘积路
- 标准的访问控制列表的配置
- LeetCode:Single Number
- android webview中调用了js的时候混淆注意事项
- PSI、TS流总结
- UVa 11233 - Deli Deli
- Android利用reative_layout生成梅花界面
- Unity3D_NGUI 灰度shader
- SQL Server 中关于EXCEPT和INTERSECT的用法