2019ICPC(南昌) Fire-Fighting Hero(最短路)

点这里获取链接

题目大意

有一个由n个点,m条边组成的无环无向图,题目保证是连通图,现在每个点代表一个着火点,有一个消防英雄和k个消防队伍比赛救火,他们的具体位置输入时会给出,谁的分数低谁就获胜,分数的定义如下:

消防英雄:到每个着火点的最短路中的最大值除以题目中给出的C,最后为了避免出现浮点数,消防英雄除以C,变成消防队伍乘以C即可,爆不了int。

消防队伍:从k个队伍中选择最优的一个消防队伍(即下半句话中描述的分数最小的队伍),也是取到每个着火点的最短路中的最大值

如果消防英雄获胜,输出消防英雄的原分数,如果消防队伍获胜,输出消防队伍的原分数,如果平局,算是消防英雄获胜

这题我知道是Dijkstra,但是题目没看懂,真的难受。其中1和4是已经确定了消防车的其实地点,所以1到4和4到1都是0
因为消防车没有固定点出发,所以从0开始,而英雄已经固定从s点开始
有一点没有弄懂:为什么INF定义为0x3f3f3f3f就可以,定义成999999999就输出为0?

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 1010
#define INF 0x3f3f3f3f
int T,v,e,s,k,c;
struct Node{
    int p;
    int val;
    Node(int _p,int _val):p(_p),val(_val){}
};
vector<Node>G[maxn];
void insert(int st,int en,int len){
    G[st].push_back(Node(en,len));
}
int dis[maxn];
int vis[maxn];
int dijkstra(int st){
    queue<int>q;
    memset(vis,0,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    q.push(st);
    dis[st]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=0;i<G[x].size();i++){
            int p=G[x][i].p;
            if(dis[p]>dis[x]+G[x][i].val){
                dis[p]=dis[x]+G[x][i].val;
                if(!vis[p]){
                    q.push(p);
                    vis[p]=1;
                }
            }
        }
    }
    return 0;
}

int st,en,len;
int main(){
    cin>>T;
    while(T--){
        for(int i=0;i<maxn-2;i++)
            G[i].clear();
        cin>>v>>e>>s>>k>>c;
        for(int i=0;i<k;i++){
            cin>>st;
            insert(0,st,0);
        }
        for(int i=0;i<e;i++){
            cin>>st>>en>>len;
            insert(st,en,len);
            insert(en,st,len);
        }
        //因为消防车没有出发地点,直接用0就行了
        dijkstra(0);
        int ans1=0,ans2=0;
        for(int i=1;i<=v;i++)
            ans1=max(ans1,dis[i]);
        //英雄是从s出发
        dijkstra(s);
        for(int i=1;i<=v;i++)
            ans2=max(ans2,dis[i]);
        //这里比较如果用除的话不太准确,所以用ans1*c
        if(ans1*c>=ans2)
            cout<<ans2<<endl;
        else
            cout<<ans1<<endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值