zoukankan      html  css  js  c++  java
  • [GXOI/GZOI2019]旅行者

    Luogu5304

    给定一个单向图和一些关键点,求所有关键点对中最短的单向距离

    以所有点为起点,正反两边跑(dijkstra),用每一条边来更新答案。

    注意两个端点不能由同一个关键点更新得来。

    多组数据记得把图清空!

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    #define Debug(x) cout<<#x<<"="<<x<<endl
    //#define int long long
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pli;
    const LL INF=1e18+7;
    inline LL read(){
        register LL x=0,f=1;register char c=getchar();
        while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
        while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
        return f*x;
    }
    
    const int N=1e5+5;
    const int M=5e5+5;
    
    struct Edge{
        int v,w,nxt;
    }e[M];
    int first[N],Ecnt=0;
    inline void Add_edge(int u,int v,int w=0){
        e[++Ecnt]=(Edge){v,w,first[u]};
        first[u]=Ecnt;
    }
    
    LL dis[2][N];int col[2][N];
    int x[M],y[M],w[M],city[N];
    bool vis[N];
    int n,m,K;LL ans;
    
    inline void dijkstra(LL *dis,int *col){
        priority_queue <pli,vector<pli>,greater<pli> > q;
        for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=false;//基本操作
        for(int i=1;i<=K;i++) dis[city[i]]=0,col[city[i]]=city[i],q.push(pli(0,city[i]));
        while(!q.empty()){
            int u=q.top().second;q.pop();
            if(vis[u]) continue;
            vis[u]=true;
            for(int i=first[u];i;i=e[i].nxt){
                int v=e[i].v,w=e[i].w;
                if(dis[u]+w<dis[v]){
                    dis[v]=dis[u]+w;
                    col[v]=col[u];
                    q.push(pli(dis[v],v));
                }
            }
        }
    }
    
    inline void solve(){
        n=read(),m=read(),K=read();
        ans=INF;
        for(int i=1;i<=n;i++) first[i]=0;
        Ecnt=0;
        for(int i=1;i<=m;i++){
            x[i]=read(),y[i]=read(),w[i]=read();
            if(x[i]!=y[i]) Add_edge(x[i],y[i],w[i]);
        }
        for(int i=1;i<=K;i++) city[i]=read();
        dijkstra(dis[0],col[0]);
        for(int i=1;i<=n;i++) first[i]=0;
        Ecnt=0;///
        for(int i=1;i<=m;i++){
            if(x[i]!=y[i]) Add_edge(y[i],x[i],w[i]);//反向建边
        }
        dijkstra(dis[1],col[1]);
        for(int i=1;i<=m;i++){
            if(col[0][x[i]]&&col[1][y[i]]&&col[0][x[i]]!=col[1][y[i]])//必须要是关键点
                ans=min(ans,dis[0][x[i]]+dis[1][y[i]]+w[i]);
        }
        printf("%lld
    ",ans);
    }
    
    int main(){
    //	freopen("1.in","r",stdin);
    //	freopen("city.out","w",stdout);
        for(int i=read();i;i--) solve();
    }
    
  • 相关阅读:
    获得SQL语句的模板,自己写类似readtrace时候用
    我的HD2手机
    匹配symbols
    再送一次书
    微软急聘MOSS高手!
    邮件规则的实现
    System.Data.SQLClient.SqlConnection在Open之后为什么需要及时Close?
    windbg中无法加载mscorwks.dll, Win32 error 0n2
    Diablo3狗熊榜
    软件构架师的特点
  • 原文地址:https://www.cnblogs.com/lizehon/p/10827513.html
Copyright © 2011-2022 走看看