CCPC-Wannafly Winter Camp Day1 (Div2, onsite) F 爬爬爬山 dijkstra

题解

根据题意 当wls下降一定高度再回到原始高度之后体力值也会回复为原有值
可以将题意简化为如果想要登上高度大于h[1]+k高度的山时要将山缩减为h[1]+k的高度
按照这个规律建图 将无向边拆分为两条 通往高度大于h[1]+k的山的边代价增加与h[1]+k的高度差和0取max后平方
建图完毕后直接跑dijkstra加堆优化即可

AC代码

#include 
#include 
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 10;
ll a[MAXN], cot[MAXN];
int n, m, k;
bool vis[MAXN];

struct node
{
	ll v, w;
	bool operator < (const node &oth) const
	{
		return w > oth.w;
	}
};
vector<node> e[MAXN];
void dijkstra()
{
	memset(cot, 0x3f, sizeof(cot));
	cot[1] = 0;
	priority_queue<node> pq;
	pq.push({ 1, 0 });
	while (!pq.empty())
	{
		ll u = pq.top().v, c = pq.top().w;
		pq.pop();
		vis[u] = 1;
		for (node &i : e[u])
			if (!vis[i.v] && c + i.w < cot[i.v])
				cot[i.v] = c + i.w, pq.push({ i.v, cot[i.v] });
	}
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	for (int i = 1; i <= m; i++)
	{
		ll u, v, w;
		scanf("%lld%lld%lld", &u, &v, &w); //通往高度大于h[1]+k的山的边代价增加
		e[u].push_back({ v, w + max(0LL, a[v] - a[1] - k) * max(0LL, a[v] - a[1] - k) });
		e[v].push_back({ u, w + max(0LL, a[u] - a[1] - k) * max(0LL, a[u] - a[1] - k) });
	}
	dijkstra();
	cout << cot[n] << endl;

	return 0;
}

你可能感兴趣的:(___图论___,dijkstra,2019,CCPC-Wannafly,Winter,Camp)