解题报告:【kuangbin带你飞】专题四 最短路练习题

目录

Kuangbin带你飞 专题四 最短路径 习题报告

A. POJ - 2387 T i l   t h e   C o w s   C o m e   H o m e Til\ the\ Cows\ Come\ Home Til the Cows Come Home--------(最短路模板题)【普及/提高-

Bessie is out in the field and wants to get back to the barn to get as
much sleep as possible before Farmer John wakes her for the morning
milking. Bessie needs her beauty sleep, so she wants to get back as
quickly as possible.

Farmer John’s field has N (2 <= N <= 1000) landmarks in it, uniquely
numbered 1…N. Landmark 1 is the barn; the apple tree grove in which
Bessie stands all day is landmark N. Cows travel in the field using T
(1 <= T <= 2000) bidirectional cow-trails of various lengths between
the landmarks. Bessie is not confident of her navigation ability, so
she always stays on a trail from its start to its end once she starts
it.

Given the trails between the landmarks, determine the minimum distance
Bessie must walk to get back to the barn. It is guaranteed that some
such route exists. Input

  • Line 1: Two integers: T and N

  • Lines 2…T+1: Each line describes a trail as three space-separated integers. The first two integers are the landmarks between which the
    trail travels. The third integer is the length of the trail, range
    1…100. Output

  • Line 1: A single integer, the minimum distance that Bessie must travel to get from landmark N to landmark 1.

最短路模板题

const int N = 50007;
const int INF = 0x3f3f3f3f;
typedef pair<int,int> PII;

int head[N],edge[N << 1],nex[N << 1],ver[N << 1],tot;
int n,m,a[N];
int dis[N];

void add(int u,int v,int val){
   
    ver[++tot] = v;
    nex[tot] = head[u];
    edge[tot] = val;
    head[u] = tot;
}

void dijkstra(int s){
   
    //memset(vis,0,sizeof vis);
    for(int i = 1;i <= n;++i)
        dis[i] = INF;
    priority_queue<PII,vector<PII>,greater<PII> >q;
    dis[s] = 0;
    q.push({
   0,1});
    while(q.size()){
   
        int x = q.top().second;
        int d = q.top().first;
        q.pop();
        if(d != dis[x])continue;
        for(int i = head[x];i;i = nex[i]){
   
            int y = ver[i],z = edge[i];
            if(dis[y] > dis[x] + z){
   
                dis[y] = dis[x] + z;
                q.push({
   dis[y],y});
            }
        }
    }
}

int main(){
   
    while(~scanf("%d%d",&m,&n)){
   
        memset(head,0,sizeof head);
        for(int i = 1;i <= m;++i){
   
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        dijkstra(1);
        printf("%d\n",dis[n]);
    }
    return 0;
}

B. POJ - 2253 F r o g g e r Frogger Frogger -------- (Floyd基础应用)【普及/提高-

Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he
notices Fiona Frog who is sitting on another stone. He plans to visit
her, but since the water is dirty and full of tourists’ sunscreen, he
wants to avoid swimming and instead reach her by jumping.
Unfortunately Fiona’s stone is out of his jump range. Therefore Freddy
considers to use other stones as intermediate stops and reach her by a
sequence of several small jumps. To execute a given sequence of jumps,
a frog’s jump range obviously must be at least as long as the longest
jump occuring in the sequence. The frog distance (humans also call it
minimax distance) between two stones therefore is defined as the
minimum necessary jump range over all possible paths between the two
stones.

You are given the coordinates of Freddy’s stone, Fiona’s stone and all
other stones in the lake. Your job is to compute the frog distance
between Freddy’s and Fiona’s stone. Input The input will contain one
or more test cases. The first line of each test case will contain the
number of stones n (2<=n<=200). The next n lines each contain two
integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of
stone #i. Stone #1 is Freddy’s stone, stone #2 is Fiona’s stone, the
other n-2 stones are unoccupied. There’s a blank line following each
test case. Input is terminated by a value of zero (0) for n. Output
For each test case, print a line saying “Scenario #x” and a line
saying “Frog Distance = y” where x is replaced by the test case number
(they are numbered from 1) and y is replaced by the appropriate real
number, printed to three decimals. Put a blank line after each test
case, even after the last one.
题目描述
一只叫 Freddy 的青蛙蹲坐在湖中的一块石头上,突然他发现一只叫 Fiona 的青蛙在湖中的另一块石头上。 Freddy 想要跟 Fiona 约会,但由于湖水太脏,他不想游泳过去而是跳过去找Fiona。很不幸,Fiona 所在的石头距离他有点远,甚至超出了他的跳跃能力。然而 Freddy 注意到湖中还有一些其他的石头。这些石头也许会将这个很长的跳跃距离化成若干个短的跳跃距离。我们定义“青蛙距离”为 Freddy 跳到 Fiona 那里所需要的若干次跳跃中最长的那一次。 现在给你 Freddy,Fiona,以及湖中其他石头的坐标,让你求出最短的“青蛙距离”。

首先是这里不是普通的最短路,需要求的最短路是最大单次跳跃距离最小化。需要用到动规的思想,加上数据只有n = 200,所以可以选择Floyd 。当然dijkstra也能过

const int N = 507;
const int INF = 0x3f3f3f3f;
typedef pair<int,int> PII;
/*
int head[N],edge[N << 1],nex[N << 1],ver[N << 1],tot;

void add(int u,int v,int val){
    ver[++tot] = v;
    nex[tot] = head[u];
    edge[tot] = val;
    head[u] = tot;
}
*/
int n,m;
int dis[N];
double G[N][N];
int t = 1;

struct node{
   
    int x,y;
}a[N];

double distances(int x1,int y1,int x2,int y2){
   
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

int main(){
   
    while(~scanf("%d",&n) && n){
   
            memset(G,0x3f,sizeof G);
        for(int i = 1;i <= n;++i)
            scanf("%d%d",&a[i].x,&a[i].y);
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= n;++j)
                G[i][j] = distances(a[i].x,a[i].y,a[j].x,a[j].y);
        for(int k = 1;k <= n;++k)
            for(int i = 1;i <= n;++i)
                for(int j = 1;j <= n;++j)
                    G[i][j] = min(G[i][j],max(G[i][k],G[k][j]));
        cout<<"Scenario #"<<t++<<endl;
        cout<<"Frog Distance = ";
        printf("%.3f\n\n",G[1][2]);//保留三位小数
    }
}

C. POJ - 1797 H e a v y   T r a n s p o r t a t i o n Heavy\ Transportation Heavy Transportation -------- (最短路变形) 【普及/提高-

Problem You are given the plan of the city, described by the streets
(with weight limits) between the crossings, which are numbered from 1
to n. Your task is to find the maximum weight that can be transported
from crossing 1 (Hugo’s place) to crossing n (the customer’s place).
You may assume that there is at least one path. All streets can be
travelled in both directions. Input The first line contains the number
of scenarios (city plans). For each city the number n of street
crossings (1 <= n <= 1000) and number m of streets are given on the
first line. The following m lines contain triples of integers
specifying start and end crossing of the street and the maximum
allowed weight, which is positive and not larger than 1000000. There
will be at most one street between each pair of crossings. Output The
output for every scenario begins with a line containing “Scenario
#i:”, where i is the number of the scenario starting at 1. Then print a single line containing the maximum allowed weight that Hugo can
transport to the customer. Terminate the output for the scenario with
a blank line.

题目大意:n个点,m条边,求1到n的一条路径上的最小权值最大化。

要注意的是前向星对于每组数据初始化的时候,head数组和tot都要初始化。

以及这里要的是最小权值最大化,所以我们起点的dis数组先设为最大值INF,然后再往优先队列里扔(0,1)。

然后注意题目的输入描述,到底是输入n,m还是m,n

const int N = 500007;
const int INF = 0x3f3f3f3f;
typedef pair<int,int> PII;

int head[N],edge[N << 1],nex[N << 1],ver[N << 1],tot;
int n,m,a[N];
int dis[N],cnt,vis[N];

void add(int u,int v,int val){
   
    ver[++tot] = v;
    nex[tot] = head[u];
    edge[tot] = val;
    head[u] = tot;
}

void dijkstra(int s){
   
    memset(vis,0,sizeof vis);
    for(int i = 1;i <= n;++i)
        dis[i] = 0;
    priority_queue<PII>q;
    dis[s] = INF;
    q.push({
   0,1});
    while(q.size()){
   
        int x = q.top().second;
        int d = q.top().first;
        q.pop();
        if(vis[x])continue;
        //if(d != dis[x])continue;
        vis[x] = 1;
        for(int i = head[x];i;i = nex[i]){
   
            int y = ver[i],z = edge[i];
            if(dis[y] < min(dis[x],z)){
   
                dis[y] = min(dis[x],z);
                q.push({
   dis[y],y});
            }
        }
    }
}

int main
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

繁凡さん

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

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

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

打赏作者

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

抵扣说明:

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

余额充值