Bridges and Tunnels

Bridges and Tunnels

Description
It may feel warm now, but in a few months, Waterloo will be full of snow. Luckily, many of the buildings on campus are connected by bridges and tunnels, so you do not need to go outside very much. The network of buildings can be confusing, and it is hard to know the best way to get from one building to another. A computer program could help.
Input
The first line of input contains three integers 0<n≤4000, 0<m≤40000, 0<p≤30, the number of buildings on campus, the number of (indoor or outdoor) paths between the buildings, and the number of trips that you would like to make. Buildings are numbered sequentially from 0 to n−1. Each of the next m lines describes a path between buildings with three integers and a letter. The first two integers specify the two buildings connected by the path. The path can be taken in either direction. The third integer specifies the number of seconds required to take the path from one building to the other. The number of seconds is at least 0 and at most one million. Finally, the letter is I if the path is indoors, or O if the path is outdoors. Each of the next p lines describes a trip from one building to another using two integers, the numbers of the two buildings.
Output
For each trip, find the optimal route between the specified two buildings. The optimal route minimizes the amount of time spent outside. Among routes that require spending the same amount of time outside, the optimal route minimizes the total time spent. For each trip, output a single line containing two integers, the time spent outside and the total time spent on the optimal route. If there is no route connecting the two specified buildings, output instead a line containing the word IMPOSSIBLE.
Samples
Input
2 1 1
0 1 30 I
0 1
Output
0 30
Source
waterloo 2012.10.13


我们常规的单源最短路是给你两个点(u,v),让你求出u到v的最短路;

这个题只是在常规最短路的基础上附加了一个条件(在外出时间最少的条件下找到两点之间的最短路),如果这里所有的边都在室外或都在室内,那么这个题就和常规最短路没有区别。
我的这里的处理方式如下:
我们增加一个数组out,表示当前点离起点的最短室外距离,u表示当前点;
1、当前边是室内的边:
out[v] > out[u]: 松弛out和dis,并将新的v,out[v],dis[v]加入队列;
out[v] == out[u] && dis[v] > dis[u] + e[u][i].w: 松弛dis,并将新的v,out[v],dis[v]加入队列;
2、当前边是室外边:
out[v] > out[u] + e[u][i].w:松弛out和dis,并将新的v,out[v],dis[v]加入队列;
out[v] == out[u] + e[u][i].w && dis[v] > dis[u] + e[u][i].w : 松弛dis,并将新的v,out[v],dis[v]加入队列;


Code:

#include<bits/stdc++.h>
#define bug(x) cout<< #x <<" = "<< x <<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> PI;
const int N = 4e4 + 10;
const int mod = 2147483648;
const ll INF=0x3f3f3f3f3f3f3f3f3f3f3f3f;
int n,m,p;
struct Node {
	int now;
	ll outdis,sumdis;
	friend bool operator<(Node x,Node y) {
		if(x.outdis == y.outdis) return x.sumdis > y.sumdis;
		return x.outdis > y.outdis;
	}
};
struct edge {
	int to;
	ll w;
	char op;
};
ll out[N],dis[N];
vector<edge> e[N];
void dijkstra(int st) {
	memset(out,INF,sizeof(out));
	memset(dis,INF,sizeof(dis));
	priority_queue<Node> q;
	out[st] = dis[st] = 0;
	q.push({st,0,0});
	while(q.size()) {
		Node tep = q.top();
		q.pop();
		int u = tep.now;
		for(int i=0; i<e[u].size(); i++) {
			int v = e[u][i].to;
			if(e[u][i].op == 'I') {
				if(out[v] > out[u]) {
					out[v] = out[u];
					dis[v] = dis[u] + e[u][i].w;
					q.push({v,out[v],dis[v]});
				}
				else if(out[v] == out[u] && dis[v] > dis[u] + e[u][i].w) {
					dis[v] = dis[u] + e[u][i].w;
					q.push({v,out[v],dis[v]});
				}
			} else {
				if(out[v] > out[u] + e[u][i].w) {
					out[v] = out[u] + e[u][i].w;
					dis[v] = dis[u] + e[u][i].w;
					q.push({v,out[v],dis[v]});
				} else if(out[v] == out[u] + e[u][i].w && dis[v] > dis[u] + e[u][i].w) {
					dis[v] = dis[u] + e[u][i].w;
					q.push({v,out[v],dis[v]});
				}
			}
		}
	}
}
int main() {
	cin >> n >> m >> p;
	int u,v,w;
	char c;
	for(int i=1; i<=m; i++) {
		cin >> u >> v >> w >> c;
		e[u].push_back({v,w,c});
		e[v].push_back({u,w,c});
	}
	while(p--) {
		cin >> u >> v;
		dijkstra(u);
		if(dis[v] == INF) puts("IMPOSSIBLE");
		else printf("%lld %lld\n",out[v],dis[v]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值