zoukankan      html  css  js  c++  java
  • Dij--P4366 [Code+#4]最短路

    *传送

    题意: 给定$n$个点,求从$s$到$t$的最短路径,其中有两种走法(可以混搭):一种是走给定的m有向边($u_i$,$v_i$,$w_i$);另一种可以由任意点x到任意点y,其费用是$c$ $ imes$ ($x$ $xor$ $y$)

    朴素的建法是$O$ ($n^2$ $ imes$ $m$)的.然而事实上一个从$x$$ o$ $y$权值为$w$的边是可以被其他边取代的,我们可以把$x$拆成二进制,一位一位的修改最终到达y,此时经过的权值显然也是$w$。

    举个例子:

    假设我们要从 $001_2$​ 到 $010_2$​,我们要花费 $2^0$ +$ 2^1$ 的费用; 但是,最短路有一个 优越的性质,我们可以把边拆开来,可以先从 $001_2$​ 到$ 000_2$,再从$ 000_2$​ 到$ 010_2$,费用是一样的。

    也就是说,对于一个点$x$,我们只需要让他和$x$ $ imes$ $2^k$连边即可,这样就优化为$O$($nlogn$+$m$)了,跑一遍$dij$就好了。

    代码:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <queue> 
     6 #include <cmath>
     7 using namespace std;
     8 int n,m,c,st,sd,x,y,val;
     9 struct node{
    10     int to,next,w;
    11 }ed[5000005];
    12 int dis[5000005],vis[5000005],head[5000005],cnt;
    13 inline void add(int u,int v,int w){
    14     ed[++cnt].next=head[u];
    15     ed[cnt].to=v;
    16     ed[cnt].w=w;
    17     head[u]=cnt;
    18 }
    19 inline int read(){
    20     int x = 1,a = 0;
    21     char ch = getchar();
    22     while(ch < '0' || ch > '9'){
    23         if(ch == '-')x = -1;
    24         ch = getchar();
    25     }
    26     while(ch <= '9'&&ch >= '0'){
    27         a = a * 10 + ch - '0';
    28         ch = getchar();
    29     }
    30     return x*a;
    31 }
    32 priority_queue<pair<int,int> > q;
    33 inline void Dij(int s){
    34     q.push(make_pair(0,s));memset(vis,0,sizeof(vis));memset(dis,63,sizeof(dis));dis[s]=0;
    35     while (!q.empty()){
    36         int x = q.top().second;
    37         q.pop();
    38         if (vis[x]) continue;
    39         vis[x]=1;
    40         for (register int i = head[x];i;i=ed[i].next){
    41             int to = ed[i].to;
    42             if (dis[to]>dis[x]+ed[i].w){
    43                 dis[to]=dis[x]+ed[i].w;
    44                 q.push(make_pair(-dis[to],to));
    45             }
    46         }
    47     }
    48     return;
    49 }
    50 int main(){
    51     n=read();m=read();c=read();
    52     for (int i = 1;i <= m;i++){
    53         x=read(),y=read(),val=read();
    54         add(x,y,val);
    55     }
    56     int lgn = floor(log2(n)) + 1;
    57     n = (1 << lgn) - 1;
    58     for (register int i = 1;i <= n;i++)
    59         for (register int j = 0;j < lgn;j++)
    60             add(i,i^(1<<j),(1<<j)*c);
    61     st=read(),sd=read();
    62     Dij(st);
    63     cout<<dis[sd];
    64 }
  • 相关阅读:
    剑指 Offer 31. 栈的压入、弹出序列
    【笔记】小样本学习(Few-shot Learning)(1)
    【VS】Visual Studio 自带的反编译工具,方便了太多了。
    秋招提前批已来,万字长文教你如何增加面试大厂的成功率🔥
    Spring Boot自动配置原理与实践(二)
    MySQL是怎么解决幻读问题的?
    深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?
    深入学习Netty(4)——Netty编程入门
    HttpRunner3.X
    HttpRunner3.X
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12732809.html
Copyright © 2011-2022 走看看