题目描述
Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图。
当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动。
定义变动函数
,表示我们在图上走过一条边后,图的边权变动情况。
这里指的“图的变动”的意思是将每条边的边权代入上函数,得到的值即为该次变动后的边权。
现在 Rinne 想要知道,在这个变动的图上从 1 到 n 的最短路径。
因为 Rinne 不喜欢负数,所以她只需要你输出经过的边权权值绝对值之和最小的那个值就可以了。
输出答案保留三位小数。
输入描述:
第一行两个正整数 N,M,表示这个动态图的点数和边数。
接下来 M 行,每行三个正整数 u,v,w,表示存在一条连接点 u,v 的无向边,且初始权值为 w。
输出描述:
如果能到达的话,输出边权绝对值之和最小的答案,保留三位小数。
否则请输出 -1。
输入
3 3
1 2 2
2 3 2
3 1 3
输出
3.000
说明
题目分析
刚开始见这个题目的时候我是很懵逼的,完全不知道如何下手,想了很久很久,逐渐的有点思路了…
首先我们应该对这个函数十分的敏感,因为这就是高中数学经典的一个周期函数,经过迭代我们发现他是一个以周期为3的周期函数,经过三次之后又回到了之前的值
其次,dp指的是一种思想,在选与不选之间,取一个最优值,我们在遍历最短路的时候,只要走过一条边那么其余所有的边都会发生改变,那么我们就用dijkstra跑出所有的情况,因为最后那个点只有三种情况,我们只需要最后在三种情况中选出最小的那个,如果最小的那个存在路径那么就是我们所需要的答案
最短路dp代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
double getdis(int x, int t) //分三种情况取值
{
if (t == 0)
return abs(1.0 * x);
else if (t == 1)
return abs(1.0 / (1.0 - x));
else
return abs(1.0 - 1.0 / x);
}
struct node1
{
int to, w, next;
} e[maxn];
int n, m, tot;
int head[maxn];
void add(int u, int v, int w) //链式前向星加班
{
e[++tot].to = v;
e[tot].w = w;
e[tot].next = head[u];
head[u] = tot;
}
double dis[maxn][5];
struct node
{
int id, t;
double dis;
bool operator<(const node x) const
{
return dis > x.dis;
}
};
priority_queue<node> q;
bool vis[maxn]