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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章