UVa10246 - Asterix and Obelix(最短路径变形)

After winning a gruesome battleagainst the Romans in a far-away land, Asterix and his dearest friend Obelixare now returning home. However Obelix is not with Asterix now. He has leftAsterix in order to deliver menhir to one of his international buyers (as youprobably know, recently he has extended his trade to international markets).But he has promised to join Asterix on his way home and Asterix has promised tohost a feast for Obelix (you know how fat he is!) in the city they meet. Obelixmay meet Asterix in any city on his way home including the starting and thedestination city.

 

 

Now Asterix is sitting with a mapand trying to figure out the cheapest route home. The map shows the cities andthe cost (in sestertii) of going from one city to another if there is a roadconnecting them directly. For each city in the map Asterix has also calculatedthe cost (in sestertii) of hosting a feast for Obelix in that city. There willbe only one feast and for safety Asterix has decided to set aside enoughsestertii to host a feast in the costliest city on the route.

 

Since Asterix does not have acomputer, he seeks your help to find out the cheapest route home.

 

Input

 

The input may contain multipletest cases.

 

The first line of each test casecontains three integers C (£ 80), R (£1000) and Q (£ 6320) where C indicates thenumber of cities (cities are numbered using distinct integers ranging from 1 toC),Rrepresents the number of roads and Q is the number of queries.

 

The next line contains Cintegers where the i-th integer fi isthe cost (in sestertii) of hosting a feast in city i.

 

Each of the next Rlines contains three integers: c1, c2 (¹ c1) and dindicating that the cost of going from city c1 to c2 (orfrom c2 toc1)is d sestertii.

 

Each of the next Qlines contains two integers c1 and c2(c1 ¹ c2)asking for the cost (in sestertii) of the cheapest route from city c1 to city c2.

 

The input will terminate withthree zeros form C, S and Q.

 

Output

 

For each test case in the inputfirst output the test case number (starting from 1) as shown in the sampleoutput. Then for each query in the input print a line giving the minimum cost(in sestertii) of going from the first to the second city in the query. Ifthere exists no path between them just print “–1”.

 

Print a blank line between twoconsecutive test cases.

 

SampleInput

 

7 8 5

2 3 5 15 4 4 6

1 2 20

1 4 20

1 5 50

2 3 10

3 4 10

3 5 10

4 5 15

6 7 10

1 5

1 6

5 1

3 1

6 7

4 4 2

2 1 8 3

1 2 7

1 3 5

2 4 8

3 4 6

1 4

2 3

0 0 0

 

SampleOutput

 

Case#1

45

-1

45

35

16

 

Case#2

18

20

题意:在从s到t的路径中选取一点u,使得u点的权值最大,其它的点的权值小于u点的权值, 并且从s到t的路径最短

思路:找到从u到s和从u到t的最短路径,使得路径上点的权值小于等于u点的权值,用Dijkstra或者SPFA找到从s点到其它点的最短路径(路径上的点的权值都小于等于s点的权值),然后查找min{f[s][u] + f[u][t] + cost[u]}的最小值即可

Dijkstra法代码如下,用的时间为0.046s

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 90;
const int INF = 0x3f3f3f3f;

struct Edge
{
    int from, to, w;
};

struct Node
{
    int u, d;
    
    bool operator < (const Node &other) const
    {
        return d > other.d;
    }
};

vector<int> adjList[MAXN];
vector<Edge> edges;
int cost[MAXN];
int f[MAXN][MAXN];
int c, r, q;
int d[MAXN];
bool vis[MAXN];
int cas = 1;

void addEdge(int u, int v, int w)
{
    edges.push_back((Edge){u, v, w});
    edges.push_back((Edge){v, u, w});
    
    int size = edges.size();
    adjList[u].push_back(size - 2);
    adjList[v].push_back(size - 1);
}

bool input()
{
    scanf("%d%d%d", &c, &r, &q);
    if (c + r + q == 0) return false;
    
    for (int i = 1; i <= c; i++) adjList[i].clear();
    edges.clear();
    
    for (int i = 1; i <= c; i++) {
        scanf("%d", &cost[i]);
    }
    
    for (int i = 0; i < r; i++) {
        int c1, c2, w;
        scanf("%d%d%d", &c1, &c2, &w);
        addEdge(c1, c2, w);
    }
    
    return true;
}

void dijkstra(int s)
{
    priority_queue<Node> q;
    for (int i = 1; i <= c; i++) {
        d[i] = INF;
    }
    
    memset(vis, false, sizeof(vis));
    d[s] = 0;
    q.push((Node){s, d[s]});
    
    while (!q.empty()) {
        Node node = q.top(); q.pop();
        
        int u = node.u;
        if (vis[u]) continue;
        vis[u] = true;
        
        for (int i = 0, size = adjList[u].size(); i < size; i++) {
            Edge& e = edges[adjList[u][i]];
            if (cost[e.to] <= cost[s] && d[u] + e.w < d[e.to]) {
                d[e.to] = d[u] + e.w;
                q.push((Node){e.to, d[e.to]});
            }
        }
    }
    
    for (int i = 1; i <= c; i++) {
        f[s][i] = d[i];
    }
}

void solve()
{
    if (cas != 1) printf("\n");
    
    printf("Case #%d\n", cas++);
    
    for (int i = 1; i <= c; i++) {
        dijkstra(i);
    }
    
    for (int i = 0; i < q; i++) {
        int c1, c2;
        scanf("%d%d", &c1, &c2);
        int ans = INF;
        for (int j = 1; j <= c; j++) {
            if (f[j][c1] == INF || f[j][c2] == INF) continue;
            ans = min(ans, f[j][c1] + f[j][c2] + cost[j]);
        }
        
        if (ans == INF) printf("-1\n");
        else printf("%d\n", ans);
    }
}

int main() 
{
#ifndef ONLINE_JUDGE
    freopen("d:\\OJ\\uva_in.txt", "r", stdin);
#endif
   
    while (input()) {
        solve();
    }
    
    return 0;
}

SPFA法代码如下,用的时间为0.042s

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 90;
const int INF = 0x3f3f3f3f;

struct Edge
{
    int from, to, w;
};

vector<int> adjList[MAXN];
vector<Edge> edges;
int cost[MAXN];
int f[MAXN][MAXN];
int c, r, q;
int d[MAXN];
bool inq[MAXN];
int cas = 1;

void addEdge(int u, int v, int w)
{
    edges.push_back((Edge){u, v, w});
    edges.push_back((Edge){v, u, w});
    
    int size = edges.size();
    adjList[u].push_back(size - 2);
    adjList[v].push_back(size - 1);
}

bool input()
{
    scanf("%d%d%d", &c, &r, &q);
    if (c + r + q == 0) return false;
    
    for (int i = 1; i <= c; i++) adjList[i].clear();
    edges.clear();
    
    for (int i = 1; i <= c; i++) {
        scanf("%d", &cost[i]);
    }
    
    for (int i = 0; i < r; i++) {
        int c1, c2, w;
        scanf("%d%d%d", &c1, &c2, &w);
        addEdge(c1, c2, w);
    }
    
    return true;
}

void spfa(int s)
{
    queue<int> q;
    for (int i = 1; i <= c; i++) {
        d[i] = INF;
    }
    
    memset(inq, false, sizeof(inq));
	d[s] = 0;
	inq[s] = true;
	q.push(s);
	
    while (!q.empty()) {
        int u = q.front(); q.pop();
		inq[u] = false;
		
        for (int i = 0, size = adjList[u].size(); i < size; i++) {
            Edge& e = edges[adjList[u][i]];
            if (cost[e.to] <= cost[s] && d[u] + e.w < d[e.to]) {
                d[e.to] = d[u] + e.w;
                if (!inq[e.to]) {
					inq[e.to] = true;
					q.push(e.to);
				}
            }
        }
    }
    
    for (int i = 1; i <= c; i++) {
        f[s][i] = d[i];
    }
}

void solve()
{
    if (cas != 1) printf("\n");
    
    printf("Case #%d\n", cas++);
    
    for (int i = 1; i <= c; i++) {
        spfa(i);
    }
    
    for (int i = 0; i < q; i++) {
        int c1, c2;
        scanf("%d%d", &c1, &c2);
        int ans = INF;
        for (int j = 1; j <= c; j++) {
            if (f[j][c1] == INF || f[j][c2] == INF) continue;
            ans = min(ans, f[j][c1] + f[j][c2] + cost[j]);
        }
        
        if (ans == INF) printf("-1\n");
        else printf("%d\n", ans);
    }
}

int main() 
{
#ifndef ONLINE_JUDGE
    freopen("d:\\OJ\\uva_in.txt", "r", stdin);
#endif
   
    while (input()) {
        solve();
    }
    
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值