Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图。
当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动。
定义变动函数 f(x)=1/(1-x),表示我们在图上走过一条边后,图的边权变动情况。
这里指的“图的变动”的意思是将每条边的边权代入上函数,得到的值即为该次变动后的边权。
现在 Rinne 想要知道,在这个变动的图上从 1 到 n 的最短路径。
因为 Rinne 不喜欢负数,所以她只需要你输出经过的边权权值绝对值之和最小的那个值就可以了。
输出答案保留三位小数。
输入描述:
第一行两个正整数 N,M,表示这个动态图的点数和边数。
接下来 M 行,每行三个正整数 u,v,w,表示存在一条连接点 u,v 的无向边,且初始权值为 w。
输出描述:
如果能到达的话,输出边权绝对值之和最小的答案,保留三位小数。
否则请输出 -1。
示例1
输入
3 3
1 2 2
2 3 2
3 1 3
输出
3.000
说明
#include<bits/stdc++.h>
using namespace std;
class ty
{
public:
ty(int to,double length,int next):to(to),length(length),next(next){
};
int to;
double length;
int next;
int times=0;
bool operator <(const ty&t) const
{
return this->length>t.length;
}
};
int head[100000+5];
double dis[100000+5][3];
vector<ty> edge;
void insertEdge(int x,int y,double length)
{
edge.emplace_back(y,length,head[x]);
head[x]=edge.size()-1;
}
double calculate(int times,double length)
{
if(times==0) return length;
else if(times==1) return 1/(length-1);
else return 1-1/length;
}
void dijkstra(int start,int end)
{
priority_queue<ty> pq;
memset(dis,0x7f,sizeof(dis));
pq.emplace(start,0,-1);
dis[start][0]=0;
while(!pq.empty())
{
int now=pq.top().to, timesNow=pq.top().times;
pq.pop();
if(now==end)
{
cout<<fixed<<setprecision(3)<<dis[end][timesNow];
return ;
}
for(int i=head[now];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(dis[v][(timesNow+1)%3]>dis[now][timesNow]+calculate(timesNow,edge[i].length))
{
dis[v][(timesNow+1)%3]=dis[now][timesNow]+calculate(timesNow,edge[i].length);
ty t=ty(v,dis[v][(timesNow+1)%3],-1);
t.times=(timesNow+1)%3;
pq.push(t);
}
}
}
cout<<-1;
return;
}
int main()
{
int n,m;
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
insertEdge(a,b,c);
insertEdge(b,a,c);
}
dijkstra(1,n);
return 0;
}