zoukankan      html  css  js  c++  java
  • 「GXOI / GZOI2019」旅行者

    题目

    我还是太傻了

    考虑每一条边的贡献,对于一条有向边((u,v,w)),我们求出(k)个关键点中到(u)最近的距离(dis_1),以及(v)(k)个关键点中最近的距离(dis_2),直接用(dis_1+w+dis_2)来更新答案就好了

    所以正反两遍(Dij)就好

    但是需要注意到一点,如果这两个点(k)个关键点中到(u)最近的点和(v)最近的·点相同,那么我们不能计入答案,因为这样只是走了一个环

    代码

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int maxn=1e5+5;
    const LL inf=9999999999999;
    inline int read() {
        char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int st[maxn],n,m,K;
    int X[maxn*5],Y[maxn*5],Z[maxn*5];
    struct Shortest {
        struct E{int v,nxt,w;}e[maxn*5];
        int head[maxn],vis[maxn],g[maxn],num;LL d[maxn];
        #define mp std::make_pair
        typedef std::pair<LL,int> pii;
        std::priority_queue<pii,std::vector<pii>,std::greater<pii> > q;
        inline void add(int x,int y,int z) {
            e[++num].v=y;e[num].nxt=head[x];e[num].w=z;head[x]=num;
        }
        inline void clear() {
            num=0;memset(head,0,sizeof(head));memset(vis,0,sizeof(vis));
        }
        inline void Dij() {
            for(re int i=1;i<=n;i++) d[i]=inf;
            for(re int i=1;i<=K;i++) d[st[i]]=0,q.push(mp(0,st[i])),g[st[i]]=st[i];
            while(!q.empty()) {
                int k=q.top().second;q.pop();
                if(vis[k]) continue;
                vis[k]=1;
                for(re int i=head[k];i;i=e[i].nxt) 
                if(d[e[i].v]>d[k]+e[i].w) {
                    d[e[i].v]=d[k]+e[i].w;g[e[i].v]=g[k];
                    q.push(mp(d[e[i].v],e[i].v));
                }
            }
        }
    }D[2];
    int main() {
        int T=read();
        while(T--) {
            D[0].clear(),D[1].clear();
            n=read(),m=read();K=read();
            for(re int x,y,z,i=1;i<=m;i++) {
                x=read(),y=read(),z=read();
                D[0].add(x,y,z);D[1].add(y,x,z);
                X[i]=x,Y[i]=y,Z[i]=z;
            }
            for(re int i=1;i<=K;i++) st[i]=read();
            D[0].Dij(),D[1].Dij();
            LL ans=inf;
            for(re int i=1;i<=m;i++) 
                if(D[0].g[X[i]]!=D[1].g[Y[i]]) 
                    ans=min(ans,D[0].d[X[i]]+Z[i]+D[1].d[Y[i]]);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    经典机器学习算法总结
    从0开始学Python---01
    Android-Canvas.save() Canvas.restore() 总结
    Android-属性动画原理总结
    设计模式-外观模式
    设计模式-模板方法
    设计模式-装饰者模式
    设计模式-策略模式
    设计模式-工厂方法模式
    设计模式-简单工厂模式
  • 原文地址:https://www.cnblogs.com/asuldb/p/10721251.html
Copyright © 2011-2022 走看看