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

    题目链接:戳我

    这是同学出的题,真心神仙qwq

    我们进行二进制分组,因为如果答案是(k_i)(k_j)之间的距离的话,他们的编号必定在某一位上不一样。
    所以这样子做是对的。跑dij的次数降低到2*log次。

    不过最好还是不要像我一样懒,分组之后重新加边,不加O2会慢死的........

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #define ss 0
    #define tt n+1
    #define MAXN 100010
    #define MAXM 500010
    using namespace std;
    int n,m,t,T,k,cnt_a,cnt_b;
    int head[MAXN],done[MAXN],kkk[MAXN];
    long long ans;
    long long dis[MAXN];
    vector<int>G[MAXN];
    struct Node
    {
        int u;
        long long d;
        friend bool operator < (Node x,Node y)
        {return x.d>y.d;}
    };
    struct Edge{int nxt,to,dis;}edge[MAXM<<1];
    struct Line{int x,y,w;}line[MAXM];
    inline void add(int from,int to,int dis)
    {
        // printf("[%d %d] %d
    ",from,to,dis);
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis;
        head[from]=t;
    }
    
    inline void dij(int s)
    {
        priority_queue<Node>q;
        for(int i=0;i<=n+1;i++) dis[i]=0x3f3f3f3f,done[i]=0;
        dis[s]=0;
        q.push((Node){s,0});
        while(!q.empty())
        {
            int u=q.top().u;q.pop();
            if(done[u]) continue;
            done[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].dis)
                {
                    dis[v]=dis[u]+edge[i].dis;
                    q.push((Node){v,dis[v]});
                }
            }
        }
    }
    inline void solve_1(int x)
    {
        t=0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=k;i++)
        {
            if(kkk[i]&(1<<x)) add(ss,kkk[i],0);
            else add(kkk[i],tt,0);
        }
        for(int i=1;i<=m;i++) add(line[i].x,line[i].y,line[i].w);
        dij(ss);
        ans=min(ans,dis[tt]);
        // printf("dis[tt]=%lld
    ",dis[tt]);
    }
    inline void solve_2(int x)
    {
        t=0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=k;i++)
        {
            if(kkk[i]&(1<<x)) add(kkk[i],tt,0);
            else add(ss,kkk[i],0);
        }
        for(int i=1;i<=m;i++) add(line[i].x,line[i].y,line[i].w);
        dij(ss);
        ans=min(ans,dis[tt]);
        // printf("dis[tt]=%lld
    ",dis[tt]);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1;i<=m;i++)
                scanf("%d%d%d",&line[i],&line[i].y,&line[i].w);
            for(int i=1;i<=k;i++) scanf("%d",&kkk[i]);
            ans=0x3f3f3f3f3f3f3f3f;
            for(int i=0;i<=17;i++)
            {
                solve_1(i);
                solve_2(i);
                // puts("");
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11126955.html
Copyright © 2011-2022 走看看