列表

详情


NC22600. Rinne Loves Dynamic Graph

描述

Rinne 学到了一个新的奇妙的东西叫做动态图,这里的动态图的定义是边权可以随着操作而变动的图。
当我们在这个图上经过一条边的时候,这个图上所有边的边权都会发生变动。
定义变动函数 ,表示我们在图上走过一条边后,图的边权变动情况。
这里指的“图的变动”的意思是将每条边的边权代入上函数,得到的值即为该次变动后的边权。
现在 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

说明:

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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 335ms, 内存消耗: 26584K, 提交时间: 2019-02-10 01:00:44

#include<stdio.h>
#include<queue>
#define fo(i,a,b) for(int i=a;i<=b;i++)
int n,m,xx,yy,zz,be[110000],et,nv;
struct edg{
	int y,ne;
	double z[3];
};
edg e[620000];
inline void add_edge(int x,int y,double z){
	e[++et].y=y;
	e[et].ne=be[x];
	e[et].z[0]=z;
	e[et].z[1]=1/(z-1);
	e[et].z[2]=(z-1)/z;
	be[x]=et;
}
double f[110000][3],oo,te;
bool b[110000][3];
struct nod{
	int u,v;
	double d;
	bool operator <(const nod a)const{
		return d>a.d;
	}
};
std::priority_queue<nod> q;
nod tn;
int main(){
	scanf("%d%d",&n,&m);
	fo(i,1,m){
		scanf("%d%d%d",&xx,&yy,&zz);
		add_edge(xx,yy,zz);
		add_edge(yy,xx,zz);
	}
	oo=1e50;
	fo(i,1,n) fo(j,0,2) f[i][j]=oo;
	f[1][0]=0;
	q.push((nod){1,0,0});
	while (!q.empty()){
		tn=q.top();q.pop();
		if (b[tn.u][tn.v]) continue;
		if (tn.u==n){
			printf("%.3f\n",tn.d);
			return 0;
		}
		b[tn.u][tn.v]=1;
		nv=tn.v+1;if (nv==3) nv=0;
		for(int i=be[tn.u];i;i=e[i].ne){
			int &y=e[i].y;
			te=tn.d+e[i].z[tn.v];
			if (te<f[y][nv]){
				f[y][nv]=te;
				q.push((nod){y,nv,te});
			}
		}
	}
	printf("-1\n");
	return 0;
}

C++ 解法, 执行用时: 634ms, 内存消耗: 49940K, 提交时间: 2021-07-14 11:32:58

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+100;
#define P pair<double,int>
int head[N],nx[N],ed[N];
double val[N];
int cnt;
double d[N];
bool vis[N];
void add(int u,int v,double w) {
	ed[++cnt]=v;
	val[cnt]=w;
	nx[cnt]=head[u];
	head[u]=cnt;
}
priority_queue<P,vector<P>,greater<P>> que;
int main() {
	int n,m;
	cin>>n>>m;
	int u,v;
	double w;
	for(int i=1; i<=m; i++) {
		cin>>u>>v>>w;
		add(u,v+n,w);
		add(v,u+n,w);
		add(u+n,v+n*2,abs(1/(1-w)));
		add(v+n,u+n*2,abs(1/(1-w)));
		add(u+2*n,v,abs((w-1)/w));
		add(v+2*n,u,abs((w-1)/w));
	}
	for(int i=1; i<N; i++) {
		d[i]=0x3f3f3f3f3f3f3f3f;
	}
	d[1]=0;
	que.push(P(0,1));
	while(que.size()) {
		P p=que.top();
		que.pop();
		int u=p.second;
		double w=p.first;
		if(vis[u])continue;
		vis[u]=1;
		for(int i=head[u]; i; i=nx[i]) {
			if(d[ed[i]]>w+val[i]) {
				d[ed[i]]=w+val[i];
				que.push(P(d[ed[i]],ed[i]));
			}
		}
	}
	double ans=min(d[n],min(d[n*2],d[n*3]));
	if(ans==d[N-1]) {
		cout<<-1<<'\n';
	} else {
		printf("%.3lf\n",ans);
	}
}

上一题