• dijkstra算法


    ①先取一点v[0]作为起始点,初始化dis[i],d[i]的值为v[0]到其余点v[i]的距离w[0][i],如果直接相邻初始化为权值,否则初始化为无限大;

    ②将v[0]标记,vis[0] = 1(vis一开始初始化为0);

    ③找寻与v[0]相邻的最近点v[k],将v[k]点记录下来,v[k]与v[0]的距离记为min;

    ④把v[k]标记,vis[k]=1;

    ⑤查询并比较,让dis[j]与min+w[k][j]进行比较,判断是直接v[0]连接v[j]短,还是经过v[k]连接v[j]更短,即dis[j]=MIN(dis[j],min+w[k][j]);

    ⑥继续重复步骤③与步骤⑤,知道找出所有点为止。

    题目

    http://cogs.pro/cogs/problem/problem.php?pid=415

    /****************************************************************************************************
    
                                            最短路—dijkstra算法(邻接表)
                            将边权替换为概率,相加改为相乘,最短距离改为最大概率
                            
    
    ********************************************************************************************************/
    #include<cstdio>
    #include<vector>
    #define MaxInt 99999999
    #define MaxN 10005
    #define eps 1e-8
    using namespace std;
    struct Edge{
        int next,to;
        double power;
    }e[6*MaxN]; 
    bool s[MaxN];// 判断是否已存入该点到S集合中
    double dis[MaxN];
    int n,m,ed[MaxN];
    void in(){
        scanf("%d%d",&n,&m);
        int x;
        for(int i=1;i<=m;i++){
            int j=i<<1;
            scanf("%d%d%lf",&x,&e[j].to,&e[j].power);
            e[j].power/=100;
            e[j].next=ed[x],ed[x]=j;
            if(x==1)dis[e[j].to]=e[j].power;
            j++;
            e[j].to=x;x=e[j-1].to,e[j].power=e[j-1].power;
            e[j].next=ed[x],ed[x]=j;
            if(x==1)dis[e[j].to]=e[j].power;
        }
    }
    void dijkstra(int v0){//v0为源点 
        s[v0]=1;dis[v0]=1;
        for(int i=1;i<n;i++){
            double min1=0;int u=v0;
            for(int j=1;j<=n;j++){// 找出当前未使用的点j的dis[j]最小值
                if(!s[j]&&dis[j]>min1+eps){
                    u=j;min1=dis[j];// u保存当前邻接点中距离最小(概率最大)的点的号码
                }
            }
            s[u]=1;
            int x=ed[u];
            while(x){//在通过新加入的u点路径找到离v0点更短的路径
                if(dis[e[x].to]<dis[u]*e[x].power-eps)dis[e[x].to]=dis[u]*e[x].power;//更新dis
                x=e[x].next;
            }
        }
    }
    int perseverance(){
        freopen("toura.in","r",stdin);
        freopen("toura.out","w",stdout);
        in();
        dijkstra(1);
        printf("%.6lf",dis[n]*100);
    }
    int come_on=perseverance();
    int main(){
        return 0;
    }

     堆优化

    /****************************************************************************************************
    
                                            最短路—dijkstra算法堆优化(邻接表)
                            将边权替换为概率,相加改为相乘,最短距离改为最大概率
                            
    
    ********************************************************************************************************/
    #include<cstdio>
    #include<queue>
    #define MaxInt 99999999
    #define MaxN 10005
    #define eps 1e-8
    using namespace std;
    struct Edge{
        int next,to;
        double power;
    }e[6*MaxN]; 
    bool s[MaxN];// 判断是否已存入该点到S集合中
    priority_queue<pair<double,int> > q;
    double dis[MaxN];
    int n,m,ed[MaxN];
    void in(){
        scanf("%d%d",&n,&m);
        int x;
        for(int i=1;i<=m;i++){
            int j=i<<1;
            scanf("%d%d%lf",&x,&e[j].to,&e[j].power);
            e[j].power/=100;
            e[j].next=ed[x],ed[x]=j;
            //if(x==1)dis[e[j].to]=e[j].power;
            j++;
            e[j].to=x;x=e[j-1].to,e[j].power=e[j-1].power;
            e[j].next=ed[x],ed[x]=j;
            //if(x==1)dis[e[j].to]=e[j].power;
        }
    }
    void dijkstra(int v0){//v0为源点 
        dis[v0]=1;
        q.push(make_pair( 1,v0));
        while(!q.empty()){
            pair<double,int>w=q.top();q.pop();// 找出当前未使用的点j的dis[j]最小值
            int u=w.second;
            if(u==n)return;
            if(s[u])continue;//使用过了 
            s[u]=1;
            int x=ed[u];
            while(x){//在通过新加入的u点路径找到离v0点更短的路径
                if(dis[e[x].to]<dis[u]*e[x].power-eps){
                    dis[e[x].to]=dis[u]*e[x].power;//更新dis
                    q.push(make_pair(dis[e[x].to],e[x].to)); 
                }
                x=e[x].next;
            }
        }
    }
    int perseverance(){
        freopen("toura.in","r",stdin);
        freopen("toura.out","w",stdout);
        in();
        dijkstra(1);
        printf("%.6lf",dis[n]*100);
    }
    int come_on=perseverance();
    int main(){
        return 0;
    }

     允许内部修改的堆优化(不用掌握)

    #include<iostream>
    using namespace std;
    struct MinBinaryHeap{
           struct node{
                int key;           
                int value;
                inline bool operator<(const node &t)const{
                     return value < t.value;   
                }          
           }*array;
           int *location,heap_size;
           MinBinaryHeap(int size){
                heap_size=0;
                    array=new node[size+1];
                    location=new int[size];
           }       
           ~MinBinaryHeap(){
                    delete[] array;    
                    delete[] location;
           }
           inline void update(int loc,const node& x){ //put x into array[loc]
                array[loc]=x;
                location[x.key]=loc;  
           }
           void per_down(int hole){
                node tem=array[hole];     
                   while(1){    
                    int child=hole<<1;     
                    if(child > heap_size)
                       break;
                    if(child!=heap_size && array[child+1] < array[child])
                       child++;
                    if(array[child] < tem){
                       update(hole,array[child]);
                       hole=child;        
                    }else break;
                }
                update(hole,tem);
           }       
           void per_up(int hole){
                node tem=array[hole];    
                   while(hole > 1){
                    if(tem < array[hole>>1]){
                       update(hole,array[hole>>1]);
                       hole>>=1;
                   }else break;
                }
                update(hole,tem);
           }
           void build_heap(int *values, int n){
                   heap_size=n;
                   for(int i=1;i<=n;i++){
                    array[i].key=i-1;
                    array[i].value=*(values++);     
                    location[array[i].key]=i;
                }
                for(int i=heap_size>>1;i>=1;i--)
                    per_down(i);            
           }
           pair<int,int> pop(){
                   pair<int,int> res=make_pair(array[1].key,array[1].value);       
                    array[1]=array[heap_size--];
                    per_down(1);
                return res;;
           }
           void decrease_to(int key,int value){
                   array[location[key]].value=value;    
                per_up(location[key]);    
           }
    };
    const int maxn=100000,INF=0x11111111;;
    struct graph{
           int node_num,allop_pt;
           struct edge{
                     int j,w;
                     edge *next;
           }*g[maxn],*pool;
           graph(int node_num,int edge_num):node_num(node_num){
                      memset(g,0,sizeof(g));
                      pool=new edge[2*edge_num];
                   allop_pt=0;
           }
           ~graph(){
                   delete[] pool;            
           }
           inline edge* new_edge(int j,int w,edge* next){
                    pool[allop_pt].j=j;
                    pool[allop_pt].w=w;
                    pool[allop_pt].next=next;
                    return &pool[allop_pt++];
           }
           inline void add_edge(int i,int j,int w){
                      g[i]=new_edge(j,w,g[i]);
                      g[j]=new_edge(i,w,g[j]);
           }       
    };
    void dijkstra(graph& g,int source, int dis[]){
         bool known[maxn]={0};
         for(int i=0;i<g.node_num;i++)dis[i]=INF;
         dis[source]=0;
         MinBinaryHeap heap(g.node_num);
         heap.build_heap(dis,g.node_num);
         for(int k=0;k<g.node_num;k++){
             pair<int,int> tem=heap.pop();        
             int i=tem.first;
             known[i]=true;
             for(graph::edge* e=g.g[i];e;e=e->next){
                      if(!known[e->j] && dis[e->j] > dis[i]+e->w){  
                         dis[e->j]=dis[i]+e->w;
                         heap.decrease_to(e->j,dis[e->j]);
                     }
             }
         }
    }
  • 相关阅读:
    oracle 处理找被删掉且提交了事务的数据
    java去除下划线并首字母大写
    假数据仓库-常见数据枚举(日期、月份、周几、星期几,前导零、Excel 列号)
    自然语言处理标注工具——Brat(安装、测试、使用)
    判断当前点击位置在不在某个区域内
    java调用C#程序集
    UE使用EditorUtilityWidget完成简单的编辑器内工具
    CodeForces 230B
    mac中安装启动使用jmeter步骤
    Ubuntu中samba配置过程
  • 原文地址:https://www.cnblogs.com/bennettz/p/6726719.html
Copyright © 2020-2023  润新知