• HDU 6166 二进制划分集合


    首先这个题化成两个集合还是很容易的想到的,但是不知道怎么用二进制表示,感觉这个题的脑洞还是很大的。

    为什么可以用二进制表示化成集合可以包含所有的点对,因为要是两个数不同的话肯定会有一个二进制的位数不同

    所以就包含了所有的点对。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=5e5;
    struct node
    {
        int u,v;
        long long w;
    }s[N];
    int node[N],nxt[N],head[N];
    int n,m,tot,begins,vis[N];
    long long d[N],data[N];
    void add(int x,int y,long long z)
    {
        node[++tot]=y;nxt[tot]=head[x];head[x]=tot;data[tot]=z;
    }
    void inist()
    {
        //memset(vis,0,sizeof(vis));
        tot=0;
        memset(node,0,sizeof(node));
        memset(head,0,sizeof(head));
        memset(data,0,sizeof(data));
    }
    void Dij()
    {
        for(int i=1;i<=n+2;i++) d[i]=10000000000000LL;
        d[begins]=0;
        priority_queue<pair<long long,long long> > heap;
        heap.push(make_pair(-d[begins],begins));
        while (1){
            for (;!heap.empty() && -d[heap.top().second]!=heap.top().first;heap.pop());
            if (heap.empty()) break;
    
            int now=heap.top().second;
            heap.pop();
    
            for (int i=head[now];i;i=nxt[i]){
                int j=node[i];
                if (d[j]>d[now]+data[i]){
                    d[j]=d[now]+data[i];
                    heap.push(make_pair(-d[j],j));
                }
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        int id=0;
        while(t--)
        {
            memset(vis,0,sizeof(vis));
            id++;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%lld",&s[i].u,&s[i].v,&s[i].w);
            }
            int k;
            scanf("%d",&k);
            for(int i=1;i<=k;i++)
            {
                int x;
                scanf("%d",&x);
                vis[x]=1;
            }
            int num=1;
            long long ans=100000000000000LL;
            while(num!=20)
            {
                inist();
                for(int i=1;i<=m;i++)
                {
                    int u=s[i].u,v=s[i].v;
                    if(vis[u])
                    {
                        if(u&(1<<(num-1)))
                        {
                            u=n+1;
                        }
                        else u=n+2;
                    }
                    if(vis[v])
                    {
                        if(v&(1<<(num-1)))
                        {
                            v=n+1;
                        }
                        else v=n+2;
                    }
                    add(u,v,s[i].w);
                }
                //begins=n+1;
               // Dij();
                //ans=min(ans,d[n+2]);
                begins=n+2;
                Dij();
                ans=min(ans,d[n+1]);
                num++;
            }
            printf("Case #%d: ",id);
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    内存管理简介之Buddy算法和slab分配
    进程通信方式介绍
    Linux内核网络栈实现分析(十一)驱动程序层(下)
    Linux内核网络协议栈深入分析(二)sk_buff的操作函数
    Linux内核网络协议栈深入分析(一)与sk_buff有关的几个重要的数据结构
    内核源码学习:伙伴算法
    寒假Day16Dinic模板更新+优化
    寒假Day20:数位dp
    寒假Day21:Catalan Square卡特兰数 JAVA写大数
    寒假Day17UVALive3231Fair Share(最大流+二分)
  • 原文地址:https://www.cnblogs.com/Heilce/p/7434731.html
Copyright © 2020-2023  润新知