M.Travel
这题是单源最短路的变形,题中需要维护两个量,到达结点i的步数,到达结点i的等级。用dijikstra 算法时每个节点先比较飞船等级,保留较低等级。等级相同再比较到达i的步数,保留步数较少的。最后更新i处的值。我在这使用cla[100005] ,dis[100005]维护i处的飞船等级和到达i的步数。
注意dijikstra算法要优化,否则超时。可以定义结构体,重载运算符,再用priority_queue优化。
代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
#include <sstream>
#define INF 107801
#define MAXN 2e5+9
#define __maxNodes 1005
const long long mod=1e6+3;
using namespace std;
struct Edge{
int from,to;
int w;
};
vector<Edge> vec[100005];
int n,m;
int dis[100005],vis[100005];
//int cp[100005];
int cla[100005];
int d,c1,e;
int ans;
struct point{
int u;
bool operator < (const point op) const{
if(cla[u]>cla[op.u]) return true;
else if(cla[u]==cla[op.u] && dis[u]>dis[op.u]) return true;
else return false;
}
};
priority_queue<point> q;
void dijk()
{
while (!q.empty())
{
point we=q.top(); q.pop();//cout << we.u << endl;
for(int i=0;i<vec[we.u].size();i++)
{
Edge ed=vec[we.u][i];
int c,st=we.u;
if(vis[ed.to]) continue;
else
vis[st]=1;
if(cla[st]*d<ed.w || cla[st]*e<=dis[st])
{
if(cla[st]*d<ed.w)
{
c=(ed.w-1)/d+1;
}
else
{
c=cla[st]+1;
}
}
else c=cla[st];
if(c>cla[ed.to]) continue;
else if(c==cla[ed.to] && dis[ed.to]<=dis[st]+1) continue;
else
{
cla[ed.to]=c;
dis[ed.to]=dis[st]+1;
}
point ne;//cout << ne.u << endl;
ne.u=ed.to;
q.push(ne);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int i;
Edge e1,e2;
for(i=0;i<=n;i++)
vec[i].clear();
scanf("%d%d%d",&c1,&d,&e);
for(i=0;i<m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
e1.from=x;e1.to=y;e1.w=z;
e2.from=y;e2.to=x;e2.w=z;
vec[x].push_back(e1);
vec[y].push_back(e2);
}
//ans=INF;
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(cla,INF,sizeof(cla));
//cout << dis[0] << endl;
dis[1]=0;cla[1]=0;vis[1]=1;
point s;s.u=1;q.push(s);
dijk();
//dfs(1,n);
printf("%d\n",cla[n]*c1);
return 0;
}