• 【最短路】【dijkstra】【二进制拆分】hdu6166 Senior Pan


    题意:给你一张带权有向图,问你某个点集中,两两结点之间的最短路的最小值是多少。

    其实就是dijkstra,只不过往堆里塞边的时候,要注意塞进去它是从集合中的哪个起始点过来的,然后在更新某个点的答案的时候,如果它是集合中的点,除了最开始入堆的那次以外,要再更新一遍,并且不能用从本身过来的路径进行更新。

    std虽然跑了20次dijkstra,但是还是有一些可取之处。

    将一个集合中的每个数进行二进制拆分,然后枚举每一位,将该位为0的归入一个半,再将该位为1的归入另一半。这样划分log次,每次只取跨越两半的点对。就必然能覆盖所有点对。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    int T,n,m,en,f[100005],head[100005],nxt[100005],to[100005],u,v,vis[100005];
    long long dis[100005],d;
    struct node{
        int from,to;
        long long dis;
        node() {}
        node(int from,int to,long long dis):from(from),to(to),dis(dis){    }
    };
    bool operator <(const node &a,const node &b)
    {
        return a.dis>b.dis;
    } 
    priority_queue<node> Q;
    void add(int u,int v,long long d)
    {
        nxt[++en]=head[u];
        head[u]=en;
        to[en]=v;
        dis[en]=d;
    }
    int main()
    {
        scanf("%d",&T);
        for(int TT=1;TT<=T;++TT)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;++i)
            {
                scanf("%d%d%lld",&u,&v,&d);
                add(u,v,d);
            }
            int t,tt;
            scanf("%d",&t);
            for(int i=1;i<=t;++i)
            {
                scanf("%d",&tt);
                f[tt]=1;
                for(int j=head[tt];j;j=nxt[j])
                {
                    Q.push(node(tt,to[j],dis[j]));
                }
            }
            node now;
            while(!Q.empty())
            {
                now=Q.top();
                Q.pop();
                if(f[now.to])
                {
                    if(now.from==now.to)
                    {
                        
                    }
                    else
                    {
                        printf("Case #%d: %lld
    ",TT,now.dis);
                        break;
                    }
                }
                else
                {
                    if(vis[now.to]<2)
                    {
                        vis[now.to]++;
                        for(int i=head[now.to];i;i=nxt[i])
                        {
                            Q.push(node(now.from,to[i],dis[i]+now.dis));
                        }
                    }
                }
            }
            while(!Q.empty()) Q.pop();
            memset(head,0,sizeof head);
            memset(f,0,sizeof f);
            memset(vis,0,sizeof vis);
            en=0;
            
        }
        return 0;
    }
  • 相关阅读:
    ENVI【遥感图像预处理之图像的几何校正】
    ENVI数据显示操作【Tools菜单操作1】
    ENVI软件操作【数据显示操作——Overlay菜单操作】
    ENVI软件操作之【数据的显示操作】
    ADO.NET操作数据库(一)
    ASP.Net之数据绑定
    动态网页的建立
    VS2010安装异常中断后无法安装的解决方法(安装时发生严重错误)
    linux vi 删除多行的方法
    简单实现异步编程promise模式
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7414471.html
Copyright © 2020-2023  润新知