【洛谷P2384】最短路 【最短路模板 dijkstra spfa】

题目背景

狗哥做烂了最短路,突然机智的考了 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
#include
#include
#include
#include
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;
}

然而……

【洛谷P2384】最短路 【最短路模板 dijkstra spfa】_第1张图片
一直最后一个点WA
不知道为啥……可能有毒瘤数据吧……

最后……

我选择用dijkstra+邻接矩阵
就过了??
下载最后一个点的我。。)
【洛谷P2384】最短路 【最短路模板 dijkstra spfa】_第2张图片

上代码:(dijkstra)

#include
#include
#include
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;
}

恩,没了……

你可能感兴趣的:(最短路,洛谷有题)