Dijkstra——最小堆优化

来源:互联网 发布:易观数据怎么样 编辑:程序博客网 时间:2024/06/17 00:11

Dijkstra+堆优化

  • 题目链接:文化之旅
  • 写完才发现这道题数据范围好小…完全可以用floyed写。不过正好顺便练练自己的代码能力orz(刚学堆优化,所以主体是剽zyh dalao的代码2333)
  • dijkstra+堆优化 思路主要是通过优先队列来贪心的把最短路放进队列,从而减少时间复杂度,变成nlog(n)。代码如下。
 #include<cstdio>    #include<cstring>    #include<iostream>    #include<queue>    using namespace std;    const int INF=0x3f;    int n,k,m,s,t;    int culture[110],head[110],dis[110],vis[110],vis2[110],node=0;    bool reject[110][110];    struct pan    {        int to,next,val;    }run[21000];    struct HeapNode{        int d,u;        bool operator < (const HeapNode &rhs )const{            return d>rhs.d;        }//重载小于号     };//用结构体来初始化优先队列 ,使其成为小根堆,来优化时间复杂度(不过这道题数据范围很小,不优化应该也能过)     void init()    {        memset(dis,INF,sizeof(dis));        for(int i=1;i<=n;i++)        {            head[i]=-1;        }    }//初始化     void add(int u,int v,int w)    {        run[++node].to=v;        run[node].val=w;        run[node].next=head[u];        head[u]=node;    }    priority_queue<HeapNode>Q;//创建优先队列     void dijkstra(int s)    {        dis[s]=0;        Q.push(HeapNode{0,s});        while(!Q.empty())//小根堆优化的dijkstra很像SPFA,也是进行入队出队的操作。         {            HeapNode x=Q.top();            int u=x.u;            Q.pop();            if(vis[u]) continue;            vis[u]=1;            for(int i=head[u];i!=-1;i=run[i].next)            {                if(culture[run[i].to]==culture[u]) continue;//如果两个地方的文化相同,那么就进行下一个循环                 if(dis[run[i].to]>dis[u]+run[i].val&&reject[u][run[i].to]==false)                {                    dis[run[i].to]=dis[u]+run[i].val;                    Q.push((HeapNode){dis[run[i].to],run[i].to});//入队                 }            }        }    }    int main()    {        int u,v,w;        cin>>n>>k>>m>>s>>t;        init();        for(int i=1;i<=n;i++)        {            cin>>culture[i];        }         if(culture[s]==culture[t])        {            cout<<-1;            return 0;        }        for(int i=1;i<=k;i++)        {            for(int j=1;j<=k;j++)            {                cin>>reject[j][i];//这个地方是j对i排斥!!!! 被这里卡了一次QAQ             }        }        for(int i=1;i<=m;i++)        {            cin>>u>>v>>w;            if(w<=run[head[u]].val||run[head[u]].val<=0)//由于两条路之间可能有多条途径,所以要特判一下             {                add(u,v,w);             }             if(w<=run[head[v]].val||run[head[u]].val<=0)            {                add(v,u,w);                         }        }        dijkstra(s);        if(dis[t]==0x3f3f3f3f) cout<<-1;//如果无法到达,就输出-1         else cout<<dis[t];        return 0;    }
原创粉丝点击