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;
    }
    
  • 相关阅读:
    ODOO开发-Pycharm开启debug模式
    pycharm开启debug模式报错汇总
    星辉Odoo模型开发教程4-常用字段属性
    星辉Odoo模型开发教程3-创建字段
    Business Object 开发
    Ubuntu安装masscan的两种方式
    HFish 蜜罐搭建测试
    【转】如何超过大多数人
    【译】13款入侵检测系统介绍
    【译】修复Ubuntu软件安装的锁文件问题
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11126955.html
Copyright © 2011-2022 走看看