题目背景

在北纬 91° ,有一个神奇的国度,叫做企鹅国。这里的企鹅也有自己发达的文明,称为企鹅文明。因为企鹅只有黑白两种颜色,所以他们的数学也是以二进制为基础发展的。

比如早在 111010011110100111101001 年前,他们就有了异或这样一个数学概念。如果你不知道异或是什么,请出门过墙左转到这里

再比如早在 100001010000101000010 年前,他们的大科学家 Penguin. Tu 就提出了最短路径这样一些概念。

题目描述

企鹅国中有 NNN 座城市,编号从 111 到 NNN 。

对于任意的两座城市 iii 和 jjj ,企鹅们可以花费 (i xor j)×C(i~\mathrm{xor}~j) \times C(i xor j)×C 的时间从城市 iii 走到城市 jjj ,这里 CCC 为一个给定的常数。

当然除此之外还有 MMM 条单向的快捷通道,第 iii 条快捷通道从第 FiF_iFi​​​ 个城市通向第 TiT_iTi​​​ 个城市,走这条通道需要消耗 ViV_iVi​​​ 的时间。

现在来自 Penguin Kingdom University SDFZ 的企鹅豆豆正在考虑从城市 AAA 前往城市 BBB 最少需要多少时间?

输入输出格式

输入格式:

从标准输入读入数据。

输入第一行包含三个整数 N,M,C,表示企鹅国城市的个数、快捷通道的个数以及题面中提到的给定的常数C。

接下来的 MMM 行,每行三个正整数 Fi,Ti,Vi (1≤Fi≤N1,1≤Ti​≤N,1≤Vi​≤100),分别表示对应通道的起点城市标号、终点城市标号和通过这条通道需要消耗的时间。

最后一行两个正整数 A,BA,BA,B (1≤C≤100),表示企鹅豆豆选择的起点城市标号和终点城市标号。

输出格式:

输出到标准输出。

输出一行一个整数,表示从城市 A 前往城市 B 需要的最少时间。

题目分析

关于SPFA:它死了。讲真我不觉得在类似网格图的东西上用SPFA是什么好办法

但即使是Dijkstra也完全无法承受如此巨大的数据范围,所以一定不是暴力建边。

折腾一下可以发现一些神奇性质:我们可以试着把这些点转成二进制,与其一下把所有位都转化成需要的数字不如一位一位转化,反正边权和是一样的。

举个例子,从00000到11111,直接一步到边权位00000 xor 11111 = 11111,我们也可以00000 -> 00001 -> 00011 -> 00111 -> 01111 -> 11111,发现这样和原来的代价是一样的!

根据这样的性质,我们只要把x和x*2^k连边就可以了(这里读作“二的k次方”,“^”不表示xor)。

再加上玄学优化的Dijkstra就可以了,堆优化好像有点悬,得吸氧

Code

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cctype>
using namespace std; const int MAXN = + ;
const int MAXM = + ;
const int INF = 0x3f3f3f3f; inline int read() {
int X = ,w = ;char ch = ;
while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}
while(isdigit(ch)) X = (X<<)+(X<<)+(ch^),ch = getchar();
return w ? -X : X;
} struct Edge {
int nxt;
int to,w;
} l[MAXM + MAXN * ];
struct Node {
int id;
int dis;
friend bool operator < (Node x,Node y) {
return x.dis > y.dis;
}
} a[MAXN]; int n,m,c;
int s,t;
int head[MAXN],cnt;
int dis[MAXN];
bool vis[MAXN];
//priority_queue <pair,vector<pair>,greater<pair>> q;
priority_queue<Node> q; void add(int x,int y,int z) {
cnt++;
l[cnt].nxt = head[x];
l[cnt].to = y;
l[cnt].w = z;
head[x] = cnt;
return;
} inline void dijkstra(int s) {
// int cur;
// memset(dis,127,sizeof(dis));
// dis[s] = 0;
// q.push(pair(0,s));
// while(!q.empty()) {
// cur = q.top().second;
// tmp = q.top().first;
// q.pop();
// if(tmp != dis[cur]) continue;
// for(int i = head[cur];i;i = l[i].nxt){
// if(dis[l[i].to] > dis[cur] + l[i].w) {
// dis[l[i].to] > dis[cur] + l[i].w
// q.push(pair(dis[l[i].to],l[i].to));
// }
// }
// }
// return;
for(int i = ;i <= n;i++) {
a[i].dis = INF;
a[i].id = i;
}
int cur;
a[s].dis = ;
q.push(a[s]);
while(!q.empty()) {
cur = q.top().id;
q.pop();
if(vis[cur]) continue;
vis[cur] = true;
for(int i = head[cur];i;i = l[i].nxt) {
if(vis[l[i].to]) continue;
if(a[l[i].to].dis > a[cur].dis + l[i].w) {
a[l[i].to].dis = a[cur].dis + l[i].w;
q.push(a[l[i].to]);
}
}
}
} int main() {
scanf("%d%d%d",&n,&m,&c);
int x,y,z;
for(register int i = ;i <= m;i++) {
x=read(),y=read(),z=read();
add(x,y,z);
}
for(register int i = ;i <= n;i++) {
for(register int j = ;j <= n;j <<= ) {
if((i ^ j) > n) continue;
add(i,i^j,j*c);
}
}
// for(int i = 1;i <= cnt;i++) {//DEBUG
// cout<<"DEBUG: "<<i<<" "<<l[i].nxt<<" "<<l[i].to<<" "<<l[i].w<<endl;
// }
scanf("%d%d",&s,&t);
dijkstra(s);
printf("%d\n",a[t].dis);
// for(int i = 1;i <= n;i++) cout<<a[i].dis<<" ";
return ;
}

[Luogu] P4366 [Code+#4]最短路的更多相关文章

  1. luogu 4366 [Code+#4]最短路 Dijkstra + 位运算 + 思维

    这个题思路十分巧妙,感觉很多题都有类似的套路. 我们发现异或操作其实就是将一个数的二进制的若干个 $0$ 变成 $1$,或者一些 $1$ 变成 $0$. 而每次按照某种顺序一位一位地异或也可以起到同时 ...

  2. [Code+#4]最短路 (最短路)

    [Code+#4]最短路 题目背景 在北纬 91° ,有一个神奇的国度,叫做企鹅国.这里的企鹅也有自己发达的文明,称为企鹅文明.因为企鹅只有黑白两种颜色,所以他们的数学也是以二进制为基础发展的. 比如 ...

  3. [Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易 ...

  4. [Code+#4]最短路 解题报告

    Luogu · 传送门 Orz THU众大佬,lct(注意不是link-cut-tree,是一个大佬) 这道题很容易让人联想到 最短路,但是最短路需要先 建图: 暴力建出所有边的算法显然是不可行的,因 ...

  5. LOJ6354 & 洛谷4366:[Code+#4]最短路——题解

    https://loj.ac/problem/6354 https://www.luogu.org/problemnew/show/P4366 题面见上面. 这题很妙,且可能是我傻,感觉这题不太好想. ...

  6. luogu 1608 路径统计--最短路计数

    https://www.luogu.org/problemnew/show/P1608 题意https://www.cnblogs.com/rmy020718/p/9440588.html相似,建议还 ...

  7. Luogu P3489 [POI2009]WIE-Hexer 最短路

    https://www.luogu.org/problemnew/show/P3489 普通的最短路,不过我觉得这个复杂度按道理来说边数不应该是m*2^13吗,不知道是数据比较水还是实际上能证明复杂度 ...

  8. luogu【P1144】最短路计数

    原题入口 这道题 一道有关于最短路的图论问题. 要求从1开始求解最短路的条数. 这个题十分有趣,首先,跑裸的spfa(或者dijkstra)算出从1开始的最短路的长度. 再其次,计数的话,可以用记忆化 ...

  9. luoguP4366 [Code+#4]最短路 最短路

    好久没写过博客了.... 本题还是挺有趣的(很水的最短路) 关键在于怎么优化这$n^2$条连边 通常,我们希望用一些边来替代一条边从而减小边集 那么,注意到异或操作可以拆分成按位运算,因此我们只需考虑 ...

随机推荐

  1. 蓝桥 ADV-232 算法提高 矩阵乘法 【区间DP】

      算法提高 矩阵乘法   时间限制:3.0s   内存限制:256.0MB      问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要 ...

  2. 关于flask的错误:ImportError: cannot import name 'Flask'

    刚开始接触flask,新创建后不能运行,报错如下图: 导致该错误有两种可能,没安装flask:文件名为flask. 可尝试如下两种方法解决: 方法一:若没安装过flask,则进入cmd,输入pip i ...

  3. 基于PHP自带的mail函数实现发送邮件以及带有附件的邮件功能

    PHPmail函数简介 bool mail ( string $to , string $subject , string $message [, string $additional_headers ...

  4. Ubuntu 16.04 安装OpenSSH7.4

      前几天突然收到接到网安总队下发通知说我们在aws里面的服务器存在重大漏洞及安全隐患.必须在规定时间内修改.我们收到邮件打开Excel发现这些问题 是由于OpenSSH版本太低导致的.于是便安排紧急 ...

  5. 牛客练习赛17-A-长方体

    题目描述 给出共享长方体一个顶点的三个面的面积,求它十二条边的边长和. 输入描述: 一行三个整数a, b, c表示面积(1 <= a, b, c <= 10000). 输出描述: 一行一个 ...

  6. C#手机充值系统开发(基于聚合数据)

    说是手机充值系统有点装了,其实就是调用了聚合数据的支付接口,其实挺简单的事 但是我发现博客园竟然没有类似文章,我就个出头鸟把我的代码贡献出来吧 首先说准备工作: 去聚合数据申请账号-添加手机支付的认证 ...

  7. Android4.4以上Uri转换成绝对路径的工具类

    一.Android4.4版本以上Uri地址封装规范: content://com.android.providers.media.documents/document/image%3A659 二.An ...

  8. 数据库学习:for xml path

    一.开发环境 数据库:SQLServer2012 二.语法简介 for xml path它以xml形式展示查询的结果集 三.语法介绍 现在数据库中有一张表 1.基本语法 select * from B ...

  9. mysql之replace into与 insert into duplicat key for update

    mysql实际应用中,我们在插入数据的时候,经常遇到主键冲突的情况,这是因为库中已经存在相同主键的数据,这时,我们只能更新数据:在判断是更新数据还是插入数据,我们还需要在此之前做一些必要的判断:在my ...

  10. 2) 十分钟学会android--建立第一个APP,执行Android程序

    通过上一节课创建了一个Android的Hello World项目,项目默认包含一系列源文件,它让我们可以立即运行应用程序. 如何运行Android应用取决于两件事情:是否有一个Android设备和是否 ...