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
    评论
Wireshark是一种网络协议分析工具,可用于捕获和分析网络数据包。Asterix是一种广泛使用的航空电子数据格式,用于将飞机的各种信息转换为二进制数据。 要在Wireshark中显示Asterix格式的数据,首先我们需要确保Wireshark已正确配置并具备解析Asterix格式的能力。Wireshark默认支持一些常见的网络协议,但对于特定的格式,我们可能需要自定义协议解析器。 在Wireshark中,为了正确解析Asterix格式的数据,我们需要创建一个自定义协议解析器。首先,我们需要了解Asterix格式的结构和字段定义。然后,我们可以使用Wireshark提供的开发工具,如Wireshark的文档和插件开发指南,来创建自定义协议解析器。 一旦我们创建了自定义协议解析器,我们可以在Wireshark中打开捕获的Asterix数据包,然后选择使用我们创建的自定义协议解析器来解析数据。Wireshark将根据我们定义的字段结构和类型,将Asterix数据包解析为易于理解和浏览的格式。 通过Wireshark的Asterix格式显示功能,我们可以查看Asterix数据包中的各个字段,例如航班号、高度、速度、位置等信息。我们还可以使用Wireshark的过滤器功能,根据特定的字段值或条件来筛选和查找感兴趣的数据。 总结来说,Wireshark提供了一种便捷的方式来显示和解析Asterix格式的数据。通过自定义协议解析器,我们可以将Asterix数据包转换为易于理解和分析的格式,并从中获取有关飞机的详细信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kgduu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值