HDU 5361 In Touch

Problem Description
There are n soda living in a straight line. soda are numbered by  1,2,,n  from left to right. The distance between two adjacent soda is 1 meter. Every soda has a teleporter. The teleporter of  i -th soda can teleport to the soda whose distance between  i -th soda is no less than  li  and no larger than  ri . The cost to use  i -th soda's teleporter is  ci .

The  1 -st soda is their leader and he wants to know the minimum cost needed to reach  i -th soda  (1in)
 

Input
There are multiple test cases. The first line of input contains an integer  T , indicating the number of test cases. For each test case:

The first line contains an integer  n   (1n2×105) , the number of soda. 
The second line contains  n  integers  l1,l2,,ln . The third line contains  n  integers  r1,r2,,rn . The fourth line contains  n  integers  c1,c2,,cn (0lirin,1ci109)
 

Output
For each case, output  n  integers where  i -th integer denotes the minimum cost needed to reach  i -th soda. If  1 -st soda cannot reach  i -the soda, you should just output -1.
 

Sample Input
   
   
   
   
1 5 2 0 0 0 1 3 1 1 0 5 1 1 1 1 1
 

Sample Output
   
   
   
   
0 2 1 1 -1
Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
 


这题的难点主要在于边的条数过多,不能像普通的最短路那样子跑。

不过此题的特点在于对于每个点来说,从这个点出去能到的任何点这个过程的花费是相同的,都是cost[i]

于是假设到达该点的距离为dis[i]则从该点能到的任何点j的值都是dis[j]=min(dis[j],dis[i]+cost[i]);

于是只要按照dis[i]+cost[i]排序,当前最先的第一个点能到的点的距离一定都是最近的,这些点在这之后都不会再被更新了。

这样只要维护一个并查集压缩路径,或者维护一个set存可能还会被更新的点就好了。


#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<functional>
using namespace std;
typedef long long LL;
const LL maxn = 200010;
LL n, T, d[maxn], l[maxn], r[maxn], c[maxn], ans, sum, fa[maxn];

void read(LL &res)
{
	char ch;
	while ((ch = getchar())<'0' || ch>'9');
	res = ch - '0';
	while ((ch = getchar()) >= '0'&&ch <= '9') res = res * 10 + ch - '0';
}

void write(LL x)
{
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

struct cmp
{
	bool operator()(const LL &a, const LL &b) const
	{
		return d[a] + c[a] > d[b] + c[b];
	}
};

LL find(LL x)
{
	if (fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

void merge(LL x, LL y)
{
	x = find(x);	y = find(y);
	if (x == y) return;
	fa[x] = y;
}

void find_dis(LL x)
{
	d[x] = 0;
	priority_queue<LL, vector<LL>, cmp> p;
	p.push(x);
	while (!p.empty())
	{
		LL q = p.top(), ll, rr;		p.pop();

		ll = q - r[q]; rr = q - l[q];
		if (rr > 0) 
			for (LL j = max(ll, (LL)1);; j++)
			{
				j = find(j);
				if (j > min(rr, n)) break;
				if (d[j]>d[q] + c[q])
				{
					d[j] = d[q] + c[q];
					p.push(j);
				}
				merge(j, j + 1);
			}

		ll = q + l[q]; rr = q + r[q];
		if (ll <= n) 
			for (LL j = ll;; j++)
			{
				j = find(j);
				if (j > min(rr, n)) break;
				if (d[j]>d[q] + c[q])
				{
					d[j] = d[q] + c[q];
					p.push(j);
				}
				merge(j, j + 1);
			}
	}
}

int main()
{
	read(T);
	while (T--)
	{
		read(n);
		sum = 0;
		for (int i = 1; i <= n; i++) read(l[i]);
		for (int i = 1; i <= n; i++) read(r[i]);
		for (int i = 1; i <= n; i++) read(c[i]), sum += c[i];
		for (int i = 1; i <= n; i++) d[i] = sum + 1;
		for (int i = 1; i <= n + 1; i++) fa[i] = i;
		find_dis(1);
		for (int i = 1; i <= n; i++)
		{
			if (i > 1) putchar(' ');
			if (d[i] == sum + 1) putchar('-'), putchar('1');
			else write(d[i]);
		}
		putchar(10);
	}
	return 0;
}


你可能感兴趣的:(HDU)