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

来源:互联网 发布:什么是网络喷子 编辑:程序博客网 时间:2024/06/05 01:56

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 andQ is the number of queries.

 

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

 

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

 

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

 

The input will terminate withthree zeros form C, S andQ.

 

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
原创粉丝点击