The 2019 Asia Nanchang First Round Online Programming Contest B. Fire-Fighting Hero 最短路+并查集

题意:有一个消防英雄在s点,k个消防点有消防队,问你消防队到任意一点的最短路的最大值与消防英雄到任意一点的最大值*1/c哪个小

题解:注意!A draw is also a victory for fire-fighting hero!即ans1<=ans2*c输出ans1!,

我贴两种办法,一种是并查集缩点建新图,另一种是把ki之间都连上权值为0的边

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const ll INF = 1e18;
const double eps = 1e-8;
const int maxn = 1000+5;
const int mod = 998244353;
int pre[maxn];
int Find(int x){
    if(pre[x]==x)return x;
    else return pre[x]=Find(pre[x]);
}
void mix(int x,int y){
    int fx=Find(x),fy=Find(y);
    if(fx!=fy){
        pre[fy]=fx;
    }
}
struct edge{int to; ll cost;
    edge(){}
    edge(int v,ll w){to=v;cost=w;}
};
struct{
    typedef pair < ll,int> P;
    int n,m;
    vector<edge>G[maxn*maxn];
    ll d[maxn*maxn];
    void dijkstra(int s){
        priority_queue<P,vector<P>,greater<P> >que;
        fill(d,d+n+1,INF);
        d[s]=0;
        que.push(P(0,s));
        while(!que.empty()){
            P p=que.top();que.pop();
            int v=p.second;
            if(d[v]<p.first)continue;
            for(int i=0;i<G[v].size();i++){
                edge e=G[v][i];
                if(d[e.to]>d[v]+e.cost){
                    d[e.to]=d[v]+e.cost;
                    que.push(P(d[e.to],e.to));
                }
            }
        }
    }
}dij1,dij2;
int v,e,s,k,c;
void init(){
    dij1.n=v;dij1.m=e;dij2.n=v;dij2.m=e;
    for(int i=0;i<=v;i++)pre[i]=i,dij1.G[i].clear(),dij2.G[i].clear();
}
int ki[maxn],ui[maxn*maxn],vi[maxn*maxn],wi[maxn*maxn];
int32_t main() 
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d",&v,&e,&s,&k,&c);
        init();
        for(int i=1;i<=k;i++)scanf("%d",&ki[i]);
        for(int i=1;i<=e;i++){
            scanf("%d%d%d",&ui[i],&vi[i],&wi[i]);
            dij1.G[ui[i]].push_back(edge(vi[i],wi[i]));
            dij1.G[vi[i]].push_back(edge(ui[i],wi[i]));
        }
        dij1.dijkstra(s);
        ll ans1=0;
        for(int i=1;i<=v;i++){
            ans1=max(ans1,dij1.d[i]);
        }
        for(int i=1;i<=k-1;i++){
            mix(ki[i],ki[i+1]);
        }
        // for(int i=1;i<=v;i++){
        //     cout<<pre[i]<<endl;
        // }
        for(int i=1;i<=e;i++){
            if(Find(ui[i])==Find(ki[1])&&Find(vi[i])==Find(ki[1])){continue;}
            dij2.G[Find(ui[i])].push_back(edge(Find(vi[i]),wi[i]));
            dij2.G[Find(vi[i])].push_back(edge(Find(ui[i]),wi[i]));
        }
        dij2.dijkstra(Find(ki[1]));
        ll ans2=0;
        for(int i=1;i<=v;i++){
            if(Find(i)==Find(ki[1]))ans2=max(ans2,1ll*0);
            else {ans2=max(ans2,dij2.d[i]);}
        }
        //cout<<ans1<<" "<<ans2<<endl;
        if(ans1<=ans2*c){//注意等号
            printf("%lld\n",ans1);
        }else printf("%lld\n",ans2);
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const ll INF = 1e18;
const double eps = 1e-8;
const int maxn = 1e3+5;
struct edge{int to,cost;
    edge(){}
    edge(int v,int w){to=v;cost=w;}
};
typedef pair < ll,int > P;
int n,m,s,k,c;
vector<edge>G[maxn*maxn];
ll d[maxn*maxn];
void dijkstra(int s){
    priority_queue<P,vector<P>,greater<P> >que;
    for(int i=1;i<=n+1;i++)d[i]=INF;
    d[s]=0;
    que.push(P(0,s));
    while(!que.empty()){
        P p=que.top();que.pop();
        int v=p.second;
        if(d[v]<p.first)continue;
        for(int i=0;i<G[v].size();i++){
            edge e=G[v][i];
            if(d[e.to]>d[v]+e.cost){
                d[e.to]=d[v]+e.cost;
                que.push(P(d[e.to],e.to));
            }
        }
    }
}
void init(){
    for(int i=1;i<=n;i++){
        G[i].clear();
    }
}
int ki[maxn];
int32_t main() 
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d",&n,&m,&s,&k,&c);
        for(int i=1;i<=k;i++){
            scanf("%d",&ki[i]);
        }
        init();
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(edge(v,w));
            G[v].push_back(edge(u,w));
        }
        dijkstra(s);
        ll ans1=0;
        for(int i=1;i<=n;i++){
            ans1=max(ans1,d[i]);
        }
        for(int i=1;i<=k-1;i++){
            G[ki[i]].push_back(edge(ki[i+1],0));
            G[ki[i+1]].push_back(edge(ki[i],0));
        }
        ll ans2=0;
        dijkstra(ki[1]);
        for(int i=1;i<=n;i++){
            ans2=max(ans2,d[i]);
        }
        //cout<<ans1<<" "<<ans2<<endl;
        if(ans1<=ans2*c){//注意等号
            printf("%lld\n",ans1);
        }else printf("%lld\n",ans2);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值