2012-2013 Waterloo Local Contest, 13 October, 2012 A题(最短路变形)

Problem A: Bridges and Tunnels

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 Specification

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.

Sample Input

2 1 1

0 1 30 I

0 1

Output Specification

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.

Output for Sample Input

0 30


题意:不久后滑铁卢将会变得非常冷,但是幸运的是,很多建筑都被桥梁和隧道连接着,所以你不需要总是走在外面。但是现在建筑

物之间的连接是错综复杂的,很难知道某两个建筑物之间的最优路线,所以需要你写程序判断。

给出 n 个点,m 条无向边,以及 p 个查询,边分为两种,一种是暴露在外面的边,用 O 表示,另一种是在室内的边,用 I 表示;最优

路线遵循以下规则:

1)尽可能使得路径上暴露在外面的边权值和最少;

2)在满足第一个条件的情况下,尽可能使得总路程最少。

每次查询给出一个 起点 s 和终点 t,求  s -> t 的最优路线。若路线存在则输出路径上暴露在外面的边的总和,以及路径的总和;否则输出

“IMPOSSIBLE”。


分析:dijkstra 最短路变形。在最短路的基础上加费用的经典变形。“规则”是最短路进行的条件,分四种情况:

用outd[v] 代表 最短路到 v 点时室外边的最小和,sumd[v] 代表到 v 点时路径总和

1)当前边属于室内边时

a) 若 outd[v] > outd[u],更新 outd[v] 以及 sumd[v],v 入队;

b) 若 outd[v] == outd[u] && sumd[v] > sumd[u] + dis[u, v],更新 outs[v] 以及 sumd[v],v 入队;

2)当前边属于室外边时

c) 若outd[v] > outd[u] + dis[u, v],更新 outd[v] 以及 sumd[v],v 入队;

d) 若 outd[v] == outd[u] + dis[u, v] && sumd[v] > sumd[u] + dis[u, v],更新 outd[v] 以及 sumd[v],v 入队。


题目链接:http://codeforces.com/gym/100169

代码清单:

/*******************************************************************************
 *** problem ID  : Bridges_and_Tunnels.cpp
 *** create time : Mon Nov 16 19:28:55 2015
 *** author name : nndxy
 *** author blog : http://blog.csdn.net/jhgkjhg_ugtdk77
 *** author motto: never loose enthusiasm for life, life is to keep on fighting!
 *******************************************************************************/

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
#include <vector>
#include <cctype>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;

#define exit() return 0

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

const int maxn = 4000 + 5;
const int maxm = 40000 + 5;
const ll maxd = 1e16 + 5;

struct Edge{
	int to, next, mark;
	ll dis;
};

struct P{
	int to;
	ll out;
	ll sum;
	P() {}
	P(int _to, ll _out, ll _sum) : to(_to), out(_out), sum(_sum) {}
	friend bool operator<(P a, P b) {
		if(a.out == b.out) return a.sum > b.sum;
		return a.out > b.out; 
	}
}; 

int n, m, p;

int head[maxn], num;
Edge graph[maxm * 2];

int a, b;
ll d;
char str[3];
ll outd[maxn];
ll sumd[maxn];


void addEdge(int u, int v, ll dis, int mark){
	graph[num].to = v;
	graph[num].dis = dis;
	graph[num].next = head[u];
	graph[num].mark = mark;
	head[u] = num++;
}

void dijkstra(int s){
	
	fill(outd, outd + n, maxd);
	fill(sumd, sumd + n, maxd);
	priority_queue <P> q;
	while(!q.empty()) q.pop();
	
	outd[s] = sumd[s] = 0;
	q.push(P(s, 0, 0));

	while(!q.empty()){
		P p = q.top(); q.pop();
		int u = p.to;
		for(int i = head[u]; i != -1; i = graph[i].next){
			int v = graph[i].to;
			if(graph[i].mark == 0){
				if(outd[v] > outd[u]){
					outd[v] = outd[u];
					sumd[v] = sumd[u] + graph[i].dis;
					q.push(P(v, outd[v], sumd[v]));
				}
				else if(outd[v] == outd[u] && sumd[v] > sumd[u] + graph[i].dis){
					outd[v] = outd[u];
					sumd[v] = sumd[u] + graph[i].dis;
					q.push(P(v, outd[v], sumd[v]));
				}
			}
			else{
				if(outd[v] > outd[u] + graph[i].dis){
					outd[v] = outd[u] + graph[i].dis;
					sumd[v] = sumd[u] + graph[i].dis;
					q.push(P(v, outd[v], sumd[v]));
				}
				else if(outd[v] == outd[u] + graph[i].dis && sumd[v] > sumd[u] + graph[i].dis){
					outd[v] = outd[u] + graph[i].dis; 
					sumd[v] = sumd[u] + graph[i].dis;
					q.push(P(v, outd[v], sumd[v]));
				}
			}
		}
	}
}

void solve(){
	num = 0;
	memset(head, -1, sizeof(head));
	scanf("%d%d%d", &n, &m, &p);
	for(int i = 0; i < m; i++){
		scanf("%d%d%I64d%s", &a, &b, &d, str);
		if(str[0] == 'I'){
			addEdge(a, b, d, 0);
			addEdge(b, a, d, 0);
		}
		else{
			addEdge(a, b, d, 1);
			addEdge(b, a, d, 1);
		}
	}
	for(int i = 1; i <= p; i++){
		scanf("%d%d", &a, &b);
		dijkstra(a);
		if(sumd[b] == maxd) printf("IMPOSSIBLE\n");
		else printf("%I64d %I64d\n", outd[b], sumd[b]);
	}
}

int main(){
	solve();
	exit();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值