Heavy Transportation(最小生成树的最大权的最短路算法)

原题链接
Heavy Transportation
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 30776 Accepted: 8174
Description

Background
Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man who tells him whether there really is a way from the place his customer has build his giant steel crane to the place where it is needed on which all streets can carry the weight.
Fortunately he already has a plan of the city with all streets and bridges and all the allowed weights.Unfortunately he has no idea how to find the the maximum weight capacity in order to tell his customer how heavy the crane may become. But you surely know.

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.
Sample Input

1
3 3
1 2 3
1 3 4
2 3 5
Sample Output

Scenario #1:
4
题意:
从s到t的每一条可行路径上都有一条单段边的最小值,有多条路径的话就求这些最小值的最大值。
对于数据,从1运到3有两种方案
方案1:1-2-3,其中1-2承重为3,2-3承重为5,则可以运送货物的最大重量是3(当大于3时明显1到不了2)
方案2:1-3,可知1-3承重为4,故此路可运送货物的最大重量是4,故答案输出4

这个题可以用dijkstra算法来做,也可以用Bellman_ford算法来做,虽然看起来好像和最短路没有关系,但是其实换个角度来想,这里其实需要用到最短的思想,最短路是寻找每次寻找最短的边加入并且更新剩余点经过v点到原点的最短路径,而这个题是每次寻找最大的承载量加入并且更新剩余点到原点的路径上经过v点后最大承载量
所以如果是用dijkstra算法的话,就是每次对剩下的点中最大承载量的那个点上与其相连的所有点进行更新。如下

#include <algorithm>
#include <iostream>
#include <utility>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
const int MOD = int(1e9) + 7;
//int MOD = 99990001;
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos(-1.0); //M_PI;
const int fx[] = {-1, 1, 0, 0};
const int fy[] = {0, 0, -1, 1};
const int maxn=1000 + 5;
int n,r,T;
int cost[maxn][maxn],d[maxn];//d[i]代表从0点到i点上的所有路径的最小值的最大值
void dijkstra(){
        bool vis[maxn];
        memset(vis,false,sizeof(vis));
        for(int i=0;i<n;i++)
                d[i]=cost[0][i];//先对这个最大承载量做一个初始化
        for(int i=0;i<n;i++){
                int maxx=-1,v;//maxx代表剩下的点中最大的承载量,v就是那个点
                for(int j=0;j<n;j++){
                        if(!vis[j] && d[j] > maxx){
                                maxx=d[j];v=j;
                        }
                }
                vis[v]=true;
                //寻找到当前的最大的承载量之后那么就需要更新下所有没有访问并且和当前的这个点有关系的所有的d[i]值
                for(int j=0;j<n;j++){
                        if(!vis[j] && d[j] < min(d[v],cost[v][j])){
                                d[j]=min(d[v],cost[v][j]);
                        }
                }
        }
        return;
}
int main(){
        cin >> T;
        for(int i=1;i<=T;i++){
                cin >> n >> r;
                //因为是要寻找最大的承载量,所以这里要初始化为0
                memset(cost,0,sizeof(cost));
                memset(d,0,sizeof(d));
                while(r--){
                        int x,y,val;
                        scanf("%d%d%d",&x,&y,&val);
                        x--;y--;
                        cost[x][y]=cost[y][x]=val;
                }
                dijkstra();
                printf("Scenario #%d:\n%d\n\n",i,d[n-1]);
                //这里的两个分行好鬼畜
        }
        return 0;
}

而Bellman_ford算法就是把不停地遍历所有的边 ,然后把边上两点代表的d值进行更新,直到不能更新的时候再停止更新

#include <algorithm>
#include <iostream>
#include <utility>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
const int MOD = int(1e9) + 7;
//int MOD = 99990001;
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-9;
const double OO = 1e20;
const double PI = acos(-1.0); //M_PI;
const int fx[] = {-1, 1, 0, 0};
const int fy[] = {0, 0, -1, 1};
const int maxn=10000 + 5;
const int maxr=maxn*maxn;

int cost[maxn][maxn],d[maxn];
int n,r,T;
void Bellman_ford(){
        for(int i=0;i<n;i++) d[i]=cost[0][i];//首先就先更新为从0到i点的路径的消耗
        while(true){
                bool flag=false;
                for(int j=0;j<n;j++){
                        for(int k=0;k<n;k++){
                                //从与其相连的边上更新路径上的最小值的最大值
                                //如果cost[k][j]==0说明两个点不直接相连
                                //既然直接相连那么在j与k之间就存在一条路径
                                //那么min(d[k],cost[k][j])就能实现更新d[j],原因是从之气有无数路径到了k,然后k又连向j,说明也有这么多的路径连向了j,同时一定经过边k-j
                                //所以如果k-j较短,但是仍然大于之前已知的到j的所有路径中的最小值的最大值,那么这个最大值肯定就要更新
                                //如果d[k]较短,但是仍然大于之前已知的到j的所有路径中的最小值的最大值,那么这个最大值肯定就要更新
                                if(d[j] < min(d[k],cost[k][j]) && cost[k][j]!=0) {d[j]=min(d[k],cost[k][j]);flag=true;}
                                if(d[k] < min(d[j],cost[j][k]) && cost[j][k]!=0) {d[k]=min(d[j],cost[j][k]);flag=true;}
                        }
                }
                if(!flag) break;
        }
        return;
}

int main(){
        cin >> T;
        for(int i=1;i<=T;i++){
                cin >> n >> r;
                for(int i=0;i<maxn;i++)
                        for(int j=0;j<maxn;j++)
                                cost[i][j]=0;
                for(int i=0;i<r;i++){
                        int x,y,val;
                        scanf("%d%d%d",&x,&y,&val);
                        x--;y--;
                        cost[x][y]=cost[y][x]=val;
                }
                Bellman_ford();
                for(int i=0;i<n;i++)
                        cout << d[i] << " " ;
                printf("Scenario #%d:\n%d\n\n",i,d[n-1]);
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

门豪杰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值