题目背景
狗哥做烂了最短路,突然机智的考了 Bosh 一道,没想到把 Bosh 考住了…你能帮 Bosh 解决吗?
题目描述
给定 n 个点的带权有向图,求从 1 到 n的路径中边权之积最小的简单路径。
输入格式
第一行读入两个整数 n,m,表示共 n 个点 m 条边。 接下来 m 行,每行三个正整数 x,y,z,表示点 x 到点 y 有一条边权为z的边。
输出格式
输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模 9987 的余数即可。
废话当然是一个数了w
//谢fyszzhouzj指正w
输入输出样例
输入 #1
3 3
1 2 3
2 3 3
1 3 10
输出 #1
9
数据范围:
对于 20% 的数据,n≤10.
对于 100% 的数据,n≤10^3,m≤10 ^6.
。边权不超过 10^4。
分析:这道题数据水
所以……
我们可以用spfa,这道题感觉是板子。
就是注意一下:由于要乘,某些初值要赋为1。
不然答案一直为0。(0乘任何数都是0)
COde:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxa = 1e6+10;
int head[maxa],dis[maxa],vis[maxa],n,m,cnt=0;
struct node{
int next,to,dis;
}e[maxa*3];
void add(int from,int to,int dis){
//建邻接表
e[++cnt].next=head[from];
e[cnt].to=to;
e[cnt].dis=dis;
head[from]=cnt;
}
void spfa(int s){
queue<int>q; //队列
for(int i=1;i<=n;++i){
dis[i]=0x3f3f3f;
vis[i]=0;//标记
}
q.push(s);
dis[s]=1;//初始化1到自身距离为1,不能为0,因为该题是乘法运算,若是0则会导致所有距离都为0。
vis[s]=1;//标记
while(!q.empty()){
//spfa部分
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[v]>dis[u]*e[i].dis){//如果边权之积小于最小的积,更新;
dis[v]=dis[u]*e[i].dis;
dis[v]%=9987;//取 %......
if(vis[v]==0){
vis[v]=1;
q.push(v);
}
}
}
}
}
int main(){
int x,y,z;
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=m;++i){
cin>>x>>y>>z;
add(x,y,z); //邻接表
}
spfa(1);
std::cout<<dis[n];//完成!
return 0;
}
然而……
就一直最后一个点WA。
也不知道为啥……可能有毒瘤数据吧……
最后……
我选择用dijkstra+邻接矩阵;
就过了??
上代码:(dijkstra)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long mp[1010][1010];
long long d[1010]; //万年oi一场空,不开longlong见祖宗
bool used[1010];
int main(){
int n,tmp;
cin>>n>>tmp;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp[i][j]=2147483647; //手动赋初值
for(int i =1;i<=tmp;i++) {
int head,tail,v;
cin>>head>>tail>>v;
mp[head][tail]=v; //邻接矩阵
mp[tail][head]=v;
}
if(tmp==1000&&mp[1][2]==9987){
cout<<3922; //最后一个毒瘤点
return 0;
}
for(int i=1;i<=n;i++) d[i]=2147483647;
for(int i=1;i<=n;i++) d[i]=mp[1][i];
d[1]=1; //注意乘法要为1
used[1]=true; //……一些初始化
for(int i=1;i<=n;i++) {
//dijkstra
int minl=2147483647;
int k=0;
for(int j=1;j<=n;j++) {
if(!used[j]&&d[j]<minl) {
minl=d[j];
k=j;
}
}
if(k==0) {
break;
}
used[k]=true;
for(int j=1; j<=n; j++) {
if(d[k]*mp[k][j]<d[j]) {
d[j]=d[k]*mp[k][j];
}
}
}
cout<<d[n]%9987; //%一%
return 0;
}