[10.4模拟赛]T2

Description

现有一个\(n\)个点,\(m\)条无向边的图。要求求出从编号为\(1\)的点到编号为\(n\)的点经过的边的边权的绝对值之和最小的路径。特别的,每经过一条边,图上所有边的边权就会改变,若原边权为\(x\),新的边权是\(\frac{1}{1-x}\)
答案保留\(3\)位小数

Input

第一行两个整数\(m\)\(n\),表示点数和边数。
接下来\(m\)行,每行三个整数\(u\)\(v\)\(x\),表示有一条连接\(u\)\(v\),边权为\(x\)

Output

\(1\)\(n\)联通,输出最小的边权的绝对值之和
否则输出"chu ti ren shi zhi zhang"(没有引号)。

Sample Input

3 1
2 3 2

Sample Output

chu ti ren shi zhi zhang

Data Constraint

对于\(30\)%的数据,\(n<=500\),\(m<=3000\)
对于\(100\)%的数据,\(n<=100000\)\(m<=300000\)\(2<=x<=1000\)

Solution

对于\(\frac{1}{1-x}\)这个式子,我们要记住它有一些性质,给一个数\(x\)
\(x->\frac{1}{1-x}->1-\frac{1}{x}->x\),所以这个数经过\(3\)次变换之后就会变回原样
我们把每个点拆成\(3\)个点,连边,跑一下最短路,就好了

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define eps 0.00001
#define MAXN 5000100
struct rec {
	int nxt, ver;
	double dis;
} t[MAXN];
struct Rec {
	int k;
	double w;
};
bool operator < (const Rec &x, const Rec &y) {
	return x.w > y.w;
}
int n, m, u, v, x, cnt;
int head[MAXN];
bool flag[MAXN];
Rec s;
priority_queue <Rec> h;
inline int read() {
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}
inline void add(int u, int v, double w) {
	t[++cnt].nxt = head[u], t[cnt].ver = v, t[cnt].dis = w, head[u] = cnt;
}
int main() {
	freopen("pb.in", "r", stdin);
	freopen("pb.out", "w", stdout);
	n = read(), m = read();
	for (register int i = 1; i <= m; i++) {
		u = read(), v = read(), x = read();
		double w = x;
		add(u, v + n, fabs(w)), add(v, u + n, fabs(w));
		add(u + n, v + 2 * n, fabs(1 / (1 - w))), add(v + n, u + 2 * n, fabs(1 / (1 - w)));
		add(u + 2 * n, v, fabs(1 - 1 / w)), add(v + 2 * n, u, fabs(1 - 1 / w));
	}
	h.push((Rec){1, 0});
	while (!h.empty()) {
		s = h.top();
		h.pop();
		if (flag[s.k]) continue;
		flag[s.k] = true;
		if (s.k == n || s.k == 2 * n || s.k == 3 * n) break;
		for (register int i = head[s.k]; i; i = t[i].nxt) {
			int v = t[i].ver;
			if (!flag[v])
				h.push((Rec){v, s.w + t[i].dis});
		}
	}
	if (s.w <= eps) printf("chu ti ren shi zhi zhang");
	else printf("%.3f", s.w);
	return 0;
}
posted @ 2019-10-04 13:16  Agakiss  阅读(100)  评论(0编辑  收藏  举报