牛客算法周周练16D Rinne Loves Dynamic Graph(分层图最短路 + 堆优化dijkstra)

在这里插入图片描述在这里插入图片描述

题目大意:

先输入节点数和边数,然后对应每条边输入起点位置和终点位置,再输入权值建图,这张图是个动态图,既每走一步,图中所有节点的权值都会发生变化,这个变化是1 / (1 - x)先观察这个函数,多代几次数,发现这是一个迭代函数,变化三次后又会回到原来的 x,这样可以根据题意分三层建图,每层只能通往更高层的位置,而第三层的下一步又会回到第一层,就可以实现动态图了,用一个邻接表存图,存图的时候权值取绝对值(题目要求)之后跑一个堆优化的迪杰斯特拉,讨论每一层的最短路即可得出答案。AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e5 + 50;
const int inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int, int> pii;
struct edge { int to, next; double val; }e[18 * N];
struct pr
{
	int d;	
	double val;
	bool operator < (const pr &t)const
	{
		return val > t.val;
	}
};
int head[3 * N], vis[3 * N], n, m, cnt = 0;
double dis[3 * N];
void add(int u, int v, double w)
{
	e[++cnt].to = v;
	e[cnt].val = w;
	e[cnt].next = head[u];
	head[u] = cnt;
}
void dijkstra(int s)
{
	memset(vis, 0, sizeof vis);
	for (int i = 1; i <= 3 * n; i ++)
	  dis[i] = inf;
	dis[1] = 0;
	priority_queue<pr > q;
	q.push({1, 0});
	while (!q.empty())
	{
		pr t = q.top();
		q.pop();
		if (vis[t.d])  continue;
		vis[t.d] = 1;
		for (int i = head[t.d]; i; i = e[i].next)
		{
			int v = e[i].to;
			if (t.val + e[i].val < dis[v])
			{
				dis[v] = t.val + e[i].val;
				q.push({v, dis[v]});
			}
		}
	}
}
int main()
{
	int u, v;
	double w;
	memset(head, 0, sizeof head);
	cin >> n >> m;
	for (int i = 1; i <= m; i ++)
	{
		cin >> u >> v >> w;
		add(u, v + n, fabs(w));
		add(v, u + n, fabs(w));
		w = (1.0 / (1 - w));
		add(u + n, v + 2 * n, fabs(w));
		add(v + n, u + 2 * n, fabs(w));
		w = (1.0 / (1 - w));
		add(u + 2 * n, v, fabs(w));
		add(v + 2 * n, u, fabs(w));
	}
	dijkstra(1);
	double ans = dis[n];
	for (int i = 0; i <= 2; i ++)
	  ans = min(ans, dis[n + i * n]);
	if (ans == inf)
	{
		cout << -1 << endl;
		return 0;
	}
	printf("%.3lf\n", ans);
	return 0;
}
posted @ 2020-07-22 16:18  Hayasaka  阅读(71)  评论(0编辑  收藏  举报