试题编号: | 201712-4 |
试题名称: | 行车路线 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 小明和小芳出去乡村玩,小明负责开车,小芳来导航。 输入格式 输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。 输出格式 输出一个整数,表示最优路线下小明的疲劳度。 样例输入 6 7 样例输出 76 样例说明 从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。 数据规模和约定 对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10; |
Dijkstra的变形。更新时,分三种情况讨论。①前一条是大路,当前是小路时,u->v经过的代价为w^2,并记w为到达点v时已走过的小路的长度,储存在sum[v]中;②前一条是小路,当前是小路时,u->v经过的代价为已走过的小路的长度sum[u]加上经过当前小路的长度w的平方,即累计已连续走过的小路的长度的平方,再减去重复计算的部分,即未经过该条小路前已连续走过的小路的长度的平方sum[u]^2;③当前是大路时,常规更新,u->v代价为w,到达点v时已连续走过的小路长度为0,故将sum[v]置零。
下面是代码:
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 512;
const int maxm = 1e5+10;
struct node
{
int x;
ll d;
node() {}
node(int X, ll D):x(X), d(D) {}
bool operator < (const node &a) const
{
if(d == a.d)
return x < a.x;
return d > a.d;
}
};
int n, m;
ll dis[maxn], sum[maxn];
int f[maxn][maxn];
vector <node> r[maxn];
void read()
{
cin >> n >> m;
for(int i = 0; i < m; ++i)
{
int opt, u, v;
ll c;
cin >> opt >> u >> v >> c;
r[u].push_back(node(v, c));
r[v].push_back(node(u, c));
if(opt == 1)
f[u][v] = f[v][u] = 1;
}
}
void dijkstra()
{
for(int i = 2; i <= n; ++i)
dis[i] = INF;
dis[1] = 0;
priority_queue <node> q;
q.push(node(1, dis[1]));
int vis[maxn] = {0};
while(!q.empty())
{
node cur = q.top();
q.pop();
if(!vis[cur.x])
{
vis[cur.x] = 1;
for(int i = 0; i < r[cur.x].size(); ++i)
{
node next = r[cur.x][i];
if(!f[cur.x][next.x]) //大路的情况
{
if(dis[next.x] > dis[cur.x]+next.d)
{
dis[next.x] = dis[cur.x]+next.d;
q.push(node(next.x, dis[next.x]));
sum[next.x] = 0;
}
}
else //小路的情况
{
if(!sum[cur.x]) //前一条路是大路
{
if(dis[next.x] > dis[cur.x]+next.d*next.d)
{
dis[next.x] = dis[cur.x]+next.d*next.d;
q.push(node(next.x, dis[next.x]));
sum[next.x] = next.d;
}
}
else //前一条路是小路
{
ll W = (sum[cur.x]+next.d)*(sum[cur.x]+next.d)-sum[cur.x]*sum[cur.x];
if(dis[next.x] > dis[cur.x]+W)
{
dis[next.x] = dis[cur.x]+W;
q.push(node(next.x, dis[next.x]));
sum[next.x] = sum[cur.x]+next.d;
}
}
}
}
}
}
}
void solve()
{
dijkstra();
cout << dis[n];
}
int main()
{
read();
solve();
return 0;
}