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

    题意:给定一个n个点,m条边的有向图,有k个被标记的点,求这k个点中任意两个点之间的最短路径的最小值。

    n<=100,000 m<=500,000

    暴力的思路:对于每个被标记的点都跑一遍dij,然后在其它被标记的点中取min,复杂度 O(k*(n+m)logn)

    对于暴力的优化:我们可以对这k个标记点进行二进制分组,分为两组,每次从set1向set2跑最短路取min,

    再从set2向set1跑一遍最短路取min,因为若存在两个点之间的最短路为最小值,这两个点的下标的二进制

    位一定有一位不一样,从而不被分在同一个组里,正确性被证明,这样只需要跑logk次即可。

    复杂度 O(logk*(n+m)logn);

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxn 100010
    #define INF 2147483647
    
    using namespace std;
    
    struct node
    {
        int ed,len,nxt;
    };
    node edge[maxn*5];
    int n,m,k,first[maxn],cnt,dis[maxn];
    int love[maxn];
    int set1_cnt,set2_cnt;
    int set1[maxn],set2[maxn];
    bool vis[maxn];
    
    inline void add_edge(int s,int e,int d)
    {
        cnt++;
        edge[cnt].ed=e;
        edge[cnt].len=d;
        edge[cnt].nxt=first[s];
        first[s]=cnt;
        return;
    }
    
    inline void dijkstra()
    {
        priority_queue < pair <int,int> > heap;
        for(register int i=1;i<=n;++i)
            dis[i]=INF,vis[i]=false;
        for(register int i=1;i<=set1_cnt;++i)
        {
            dis[set1[i]]=0;
            heap.push(make_pair(-dis[set1[i]],set1[i]));
        }
        while(!heap.empty())
        {
            int p=heap.top().second; heap.pop();
            if(vis[p]) continue;
            vis[p]=true;
            for(register int i=first[p];i;i=edge[i].nxt)
            {
                int e=edge[i].ed;
                int d=edge[i].len;
                int newd=dis[p]+d;
                if(newd<dis[e])
                {
                    dis[e]=newd;
                    heap.push(make_pair(-dis[e],e));
                }
            }    
        }
        return;
    }
    
    inline void dijkstra_2()
    {
            priority_queue < pair <int,int> > heap;
        for(register int i=1;i<=n;++i)
            dis[i]=INF,vis[i]=false;
        for(register int i=1;i<=set2_cnt;++i)
        {
            dis[set2[i]]=0;
            heap.push(make_pair(-dis[set2[i]],set2[i]));
        }
        while(!heap.empty())
        {
            int p=heap.top().second; heap.pop();
            if(vis[p]) continue;
            vis[p]=true;
            for(register int i=first[p];i;i=edge[i].nxt)
            {
                int e=edge[i].ed;
                int d=edge[i].len;
                int newd=dis[p]+d;
                if(newd<dis[e])
                {
                    dis[e]=newd;
                    heap.push(make_pair(-dis[e],e));
                }
            }    
        }
        return;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            memset(edge,0,sizeof(edge));
            memset(first,0,sizeof(first));
            cnt=0;
            scanf("%d%d%d",&n,&m,&k);
            for(register int i=1;i<=m;++i)
            {
                int s,e,d;
                scanf("%d%d%d",&s,&e,&d);
                add_edge(s,e,d);
            }
            int ans=2147483647;
            for(register int i=1;i<=k;++i)
                scanf("%d",&love[i]);
            for(register int i=0;(1<<i)<=k;++i)
            {
                set1_cnt=0;
                set2_cnt=0;
                for(register int j=1;j<=k;++j)
                {
                    if(((j>>i)&1)==0) set1[++set1_cnt]=love[j];
                    else set2[++set2_cnt]=love[j];
                }
                dijkstra();
                for(register int j=1;j<=set2_cnt;++j)
                    ans=min(ans,dis[set2[j]]);
                dijkstra_2();
                for(register int j=1;j<=set1_cnt;++j)
                    ans=min(ans,dis[set1[j]]);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Apache2支持py,pl,cgi,sh
    javascript利用Active操作本地文件
    桥接模式下的手机-电脑-开发板连接
    Django signal
    mysql改变表的编码字符集(utf8改为utf8mb4)
    Mysql 多表关联查询
    Python unicode转义字符u的处理
    How to filter a DateTimeField by date in Django?
    python闭包变量迟邦定
    Ubuntu16.04安装&创建Python虚拟环境
  • 原文地址:https://www.cnblogs.com/Hoyoak/p/11774033.html
Copyright © 2011-2022 走看看