Rinne Loves Dynamic Graph(牛客算法周周练16)

Rinne Loves Dynamic Graph(牛客算法周周练16)

Problem:

Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图。
当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动。

定义变动函数 \(f(x) = \frac{1}{1-x}\),表示我们在图上走过一条边后,图的边权变动情况。

这里指的“图的变动”的意思是将每条边的边权代入上函数,得到的值即为该次变动后的边权。

现在 Rinne 想要知道,在这个变动的图上从 1 到 n 的最短路径。
因为 Rinne 不喜欢负数,所以她只需要你输出经过的边权权值绝对值之和最小的那个值就可以了。
输出答案保留三位小数。

Input:

第一行两个正整数 N,M,表示这个动态图的点数和边数。
接下来 M 行,每行三个正整数 u,v,w,表示存在一条连接点 u,v 的无向边,且初始权值为 w。

Output:

如果能到达的话,输出边权绝对值之和最小的答案,保留三位小数。
否则请输出 -1。

Example:

Input:

3 3
1 2 2
2 3 2
3 1 3

Output:

3.000

Note:

\(1 \to 2 \to 3\),总花费 \(2 + |\frac{1}{1-2}| = 3\)

Remark:

n≤100000,m≤300000,2≤x≤1000

题解:

最短路DP,分析边权的变化公式可知:

\[f(x)=\frac{1}{1-x}\\f(f(x))=1-\frac{1}{x}\\f(f(f(x)))=x \]

所以,对于边权的值根据已走过的边数存在三种情况:

\[edge\ mod\ 3==1\to \frac{1}{1-x}\\edge\ mod\ 3==2\to 1-\frac{1}{x}\\edge\ mod\ 3==0\to x \]

Dijkstra计算最短路,记录走过边数,计算边权代入计算最小值。

Code:

/**********************************************************
* @Author: 			   Kirito
* @Date:   			   2020-06-24 21:11:15
* @Last Modified by:   Kirito
* @Last Modified time: 2020-07-23 15:36:56
* @Remark: 
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;

struct node
{
	int id,x;
	double dis;
	bool operator < (const node &b) const{
		return dis>b.dis;
	}
};

const int maxn=611111;
//graph
int first[maxn],nxt[maxn],u[maxn],v[maxn],w[maxn];
int n,m,cnt;
//dij
double dis[maxn][5];
int book[maxn][5];
//link-form
void add(int x,int y,int d)
{
	cnt++;
	u[cnt]=x;v[cnt]=y;w[cnt]=d;
	nxt[cnt]=first[u[cnt]];first[u[cnt]]=cnt;
	return;
}
//INi
void ini()
{
	for(int i=0;i<=n;i++){
		dis[i][0]=dis[i][1]=dis[i][2]=1e30;
	}
	return;
}
//getdis
double getdis(int nm,int w)
{
	switch(nm)
	{
		case 0: return fabs(1.0*w);
		case 1: return fabs(1.0/(1.0-w));
		case 2: return fabs(1.0-1.0/w);
	}
	return fabs(1.0*w);
}
//Dijkstra
void dijkstra()
{
	ini();CSE(book,0);
	priority_queue<node> box;
	box.push(node{0,1,0});dis[1][0]=0;
	while(!box.empty())
	{
		int x=box.top().x,t=box.top().id;;box.pop();
		if(book[x][t]) continue;
		book[x][t]=1;
		for(int i=first[x];i!=-1;i=nxt[i]){
			int y=v[i];
			int t2=(t+1)%3;
			double d=getdis(t,w[i])+dis[x][t];
			if(book[y][t2]) continue;
			if(dis[y][t2]>d){
				dis[y][t2]=d;
				box.push(node{t2,y,dis[y][t2]});
			}
		}
	}
	return;
}


int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	#endif
	CSE(first,-1);CSE(nxt,-1);cnt=0;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	dijkstra();
	double ans=min(dis[n][0],min(dis[n][1],dis[n][2]));
	int k=(book[n][0]|book[n][1]|book[n][2]);
	if(k)
		printf("%.3lf\n",ans);
	else
		printf("-1\n");
	return 0;
}
posted @ 2020-07-23 16:48  落水清心  阅读(98)  评论(0编辑  收藏  举报