洛谷P1266 速度限制

题意很好理解,就是给你一个图,\(n\) 个点,\(m\) 条边,每条边包含长度 \(l\),和 速度 \(v\),求从 \(0\)\(d\) 最短花多少时间,如果 \(v=0\) 那么速度为到这条边的起点时的速度,也就是保持原速不变。

我用的邻接矩阵,用结构体 \(G_{i,j}\)\(i\)\(j\) 是否有边 \((flag)\)、距离 \((l)\)、速度 \((v)\)

因为不同的速度会导致不同的结果,所以我们要把速度也标记下来。

\(dis_{i,j}\) 表示从 \(0\)\(i\) 并且到 \(i\) 时速度为 \(j\) 的最短时间,我们用 \(dijkstra+\)堆优化 求出 \(dis\),然后在 \(dis_{d,i}(0≤i≤500)\) 中找到最小的 \(dis\),把速度存下来。

最后递归输出。用结构体数组 \(pre_{i,j}\)\(dis_{i,j}\) 是由什么转移过来的。

输出的时候,就一直向前查找,直到前一个点为 \(-1\) 再输出并回溯。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define N 200
#define V 510
#define INF 0x3f3f3f3f

using namespace std;

int n,m,d;
struct point
{
	int flag,v,l;	//flag:是否有边,v:速度,l:长度 
}G[N][N];
struct node	//优先队列的类型 
{
	int u,v;	//u:节点编号,v:到u时的速度 
	double t;	//已经用了多长时间 
	node(int _u=0,int _v=0,double _t=0)
	{
		u=_u;
		v=_v;
		t=_t;
	}
	const bool operator < (const node b) const	//因为我写的大根堆,所以要反过来 
	{
		return t==b.t?v<b.v:t>b.t;	//时间越小越好,如果相等,速度越大越好 
	}
}; 
struct PRE
{
	int u,v;	//前一个点的编号和速度 
}pre[N][V];
double dis[N][V];
int vis[N][V];
priority_queue <node> que;

void dijkstra()
{
	memset(dis,0x7f,sizeof(dis));
	memset(pre,-1,sizeof(pre));
	dis[0][70]=0;
	que.push(node(0,70,dis[0][70]));
	while(!que.empty())
	{
		node p=que.top();
		que.pop();
		int i=p.u,j=p.v;
		if(vis[i][j]) continue;
		vis[i][j]=1;
		for(int k=0; k<n; k++)
		{
			if(G[i][k].flag)
			{
				if(!G[i][k].v)
				{
					if(dis[i][j]+(double)(1.0*G[i][k].l/j)<dis[k][j])
					{
						dis[k][j]=dis[i][j]+(double)(1.0*G[i][k].l/j);
						que.push(node(k,j,dis[k][j]));
						pre[k][j].u=i;
						pre[k][j].v=j;
					}
				}
				else
				{
					int v=G[i][k].v;
					if(dis[i][j]+(double)(1.0*G[i][k].l/v)<dis[k][v])
					{
						dis[k][v]=dis[i][j]+(double)(1.0*G[i][k].l/v);
						que.push(node(k,v,dis[k][v]));
						pre[k][v].u=i;
						pre[k][v].v=j;
					}
				}
			}
		}
	}
	return;
}

void print(int u,int v)
{
	if(pre[u][v].u!=-1) print(pre[u][v].u,pre[u][v].v);
	printf("%d ",u);
}

int main()
{
	scanf("%d%d%d",&n,&m,&d);
	for(int i=1; i<=m; i++)
	{
		int a,b,v,l,t=0;
		scanf("%d%d%d%d",&a,&b,&v,&l);
		G[a][b]=(point){1,v,l};
	}
	dijkstra();
	double mint=INF;
	int speed;
	for(int i=0; i<=500; i++)
	{
		if(dis[d][i]<mint)
		{
			mint=dis[d][i];
			speed=i;
		}
	}
	print(d,speed);
	return 0;
}
posted @ 2020-05-31 17:46  Acestar  阅读(174)  评论(0编辑  收藏  举报