(advanced) 最短路 UVA 12227 Wormholes

在发现宇宙中充满由外星种族创造的虫洞后,你和朋友决定乘坐飞船探索太空。你们的目标是找到最早到达目的地的时间。输入包含测试用例数、起点和终点坐标、虫洞数量及每个虫洞的入口、出口坐标和时间信息。输出应为最早到达目的地的时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem J
Wormholes

A friend of yours, an inventor, has built a spaceship recently and wants to explore space with it. During his first voyages, he discovered that the universe is full of wormholes created by some alien race. These wormholes allow one to travel to places far, far away, but moreover, they can also send you to times long ago or in the distant future.

Having mapped these wormholes and their respective end points, you and your friend boldly decide to board his spaceship and go to some distant place you’d like to visit. Of course, you want to arrive at your destination as early as possible. The question is: what is this earliest arrival time?

Input
The first line of input contains an integer c (1 ≤ c ≤ 200), the number of test cases. Each test case starts with a line containing two coordinate triples x0,y0,z0 and x1,y1,z1, the space coordinates of your departure point and destination. The next line contains an integer n (0 ≤ n ≤ 50), the number of wormholes. Then follow n lines, one for each wormhole, with two coordinate triples xs,ys,zs and xe,ye,ze, the space coordinates of the wormhole entry and exit points, respectively, followed by two integers t,d (-1000000 ≤ t,d ≤ 1000000), the creation time t of the wormhole and the time shift d when traveling through the wormhole.

All coordinates are integers with absolute values smaller than or equal to 10000 and no two points are the same.

Note that, initially, the time is zero, and that tunneling through a wormhole happens instantly. For simplicity, the distance between two points is defined as their Euclidean distance (the square root of the sum of the squares of coordinate differences) rounded up to the nearest integer. Your friend’s spaceship travels at speed 1.

Output
For each test case, print a single line containing an integer: the earliest time you can arrive at your destination.

Sample Input Sample Output
2  
0 0 0 100 0 0  
2  
1 1 0 1 2 0 -100 -2  
0 1 0 100 1 0 -150 10  
0 0 0 10 0 0  
1  
5 0 0 -5 0 0 0 0
-89  
10

题意:你要在太空里面游行!!有一些虫洞,你知道他们从什么时候开始才有,也知道他们的入口和出口以及穿越一个虫洞的时间。。。然后问到达目的的最早时间。

思路:首先这道题目即使存在负环也不会无解的。。。因为虫洞不是一直都在的。那么但存在负环的时候,我们就能一直循环到其中一个虫洞消失,而且要达到最优的话,就是这样一直循环到虫洞消失。所以这道题的难点在于寻找负环。。。。我用spfa的dfs形式找的,但是还是有很多无用功啊,因为找到的不一定是负环。可能写错了,如果找到一个负环,就把这个换里面最早消失的虫洞找出来,然后把他的距离置为它刚开始有的时间,并把它加入队列,最后我们用队列的spfa找最短路。。。。我这个过不了poj....poj要1s,丧心病狂......

代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;
#define eps 1e-8
#define LL long long
const int maxn = 1000;
const int inf = 1e8;
int n , m , size;
bool vis[maxn] , inq[maxn];
int d[maxn];
int d_tmp[maxn];
int  c;

struct Edge
{
	Edge(int uu=0,int vv=0, int tt=0,int ww=0) 
		: u(uu) , v(vv) , t(tt) ,w(ww) { }
	int u , v , w;
	int t;
}S[maxn];

struct Point
{
	Point(int xx=0,int yy=0,int zz=0) : x(xx) , y(yy) , z(zz) { }
	int x , y , z;
}point[maxn];

inline double sqr(LL x) { return x * x; }

int dist(const Point & p1,const Point & p2)
{
	return ceil(sqrt(sqr(p1.z-p2.z)+sqr(p1.x-p2.x)+sqr(p1.y-p2.y))-eps);
}

struct Node 
{
	int v;
	int t;
	int w;
	Node *next;
} edge[maxn*maxn] , *first[maxn];

void init() { m = 0 ; memset(first,0,sizeof(first)); }

void add(int x,int y, int w,int t)
{
	edge[++m].v = y;
	edge[m].w = w;
	edge[m].t = t;
	edge[m].next = first[x];
	first[x] = &edge[m];
}

void input()
{
	size = 0;
	int x , y , z;
	scanf("%d%d%d",&x,&y,&z);
	point[++size] = Point(x,y,z);
	scanf("%d%d%d",&x,&y,&z);
	point[++size] = Point(x,y,z);
	scanf("%d",&n);
	for (int i = 0 ; i < n ; ++i)
	{
		scanf("%d%d%d",&x,&y,&z);
		point[++size] = Point(x,y,z);
		int u = size;
		scanf("%d%d%d",&x,&y,&z);
		point[++size] = Point(x,y,z);
		int v = size;
		int d , t;
		scanf("%d%d",&t,&d);
		add(u,v,d,t);
	}
	for (int i = 1 ; i <= size ; ++i) {
		for (int j = i+1 ; j <= size ; ++j) {
			add(i,j,dist(point[i],point[j]),-inf);
			add(j,i,dist(point[i],point[j]),-inf);
		}
	}
}

void dfs(int u,queue<int> & q)
{
	if (vis[u]) 
	{
		int ret = c-1;
		int sum = 0;
		for (int i = c-1 ; ; --i)
		{
			if (S[ret].t < S[i].t) ret = i;
			sum += S[i].w;
			if (S[i].u==u) break;
		}
		if (sum >= 0 || S[ret].t==-inf) return;
		d_tmp[S[ret].u] = S[ret].t;
		if (!inq[S[ret].u]) q.push(S[ret].u);
		inq[S[ret].u] = true;
		return; 
	}
	vis[u] = true;
	for (Node * p = first[u] ; p ; p=p->next)
	{
		int v = p->v , w = p->w;
		if (p->t > d[u]) w += p->t-d[u];
		if (d[v] <= d[u]+w) continue;
		d[v] = d[u]+w;
		S[c++] = Edge(u,v,p->t,w);
		dfs(v,q);
		--c;
	}
	vis[u] = false;
	return;
}

void solve()
{
	memset(vis,0,sizeof(vis));
	memset(inq,0,sizeof(inq));
	queue<int> q;
	for (int i = 1 ; i <= size ; ++i) d[i] = inf;
	d[1] = 0;
	c = 0;
	dfs(1,q);
	if (!inq[1]) {
		inq[1] = true;
		q.push(1);
	}
	for (int i = 1 ; i <= size ; ++i) 
	{
		if (!inq[i]) d[i] = inf;
		else d[i] = d_tmp[i];
	}
	while (q.size())
	{
		int u = q.front(); q.pop();
		inq[u] = false;
		for (Node * p = first[u] ; p ; p=p->next)
		{
			int v = p->v , w = p->w;
			if (p->t > d[u]) w += p->t-d[u];
			if (d[v] <= d[u]+w) continue;
			d[v] = d[u]+w;
			if (inq[v]) continue;
			inq[v] = true; q.push(v);
		}
	}
	printf("%d\n",d[2]);
	//cout << d[2] << endl;
}

int main()
{
	int T; cin>>T;
	while (T--)
	{
		init();
		input();
		solve();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值