二进制分组,算个小技巧

bzoj 4398福慧双修

给一张图,同一条边不同方向权值不同,一条边只能走一次,求从1号点出发再回到1号点的最短路

一开始没注意一条边只能走一次这个限制,打了个从一号点相邻节点为原点的dij,样例就挂了

其实就是要从这个错误思路上改进

对于不与1号点相接的边,权值为正,肯定不会重复走,所以这个条件可以忽略

考虑1号点相邻的点,走出第一步后所在的点,和走回1号点前的那个点不能相同

设这两个点编号为\(i\),\(j\),则\(i\),\(j\)的二进制至少有一位不同

所以用二进制分组其实这个方法也是看来题解之后才知道的,自己想真很难想出来

枚举每个二进制位,虚拟一个源点和汇点,这位为0/1的点分成两组,分别与源/汇点相连,跑两次dij,取\(dis[1]\)的最小值

复杂度高于那种构造新图的方式,bzoj上测的总时间2s+,肯定是倒数,但想起来也能简单一些

code.

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define R register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n,m;
int fir[40006],nex[200006],to[200006],w[200006],tot;
int dui[40006],size;
int dis[40006],in[40006];
inline void push(int x){
dui[size++]=x;
R int i=size-1,fa;
while(i){
fa=i>>1;
if(dis[dui[fa]]<=dis[dui[i]]) return;
std::swap(dui[fa],dui[i]);i=fa;
}
}
inline int pop(){
int ret=dui[0];dui[0]=dui[--size];
R int i=0,ls,rs;
while((i<<1)<size){
ls=i<<1;rs=ls|1;
if(rs<size&&dis[dui[rs]]<dis[dui[ls]]) ls=rs;
if(dis[dui[ls]]>=dis[dui[i]]) break;
std::swap(dui[ls],dui[i]);i=ls;
}
return ret;
}
inline int dij(int bit,int panduan){
std::memset(dis,0x3f,sizeof dis);
for(R int i=fir[1];i;i=nex[i])if((to[i]&bit)==panduan){
push(to[i]);dis[to[i]]=w[i];in[to[i]]=1;
}
while(size){
R int u=pop();in[u]=0;
for(R int i=fir[u];i;i=nex[i]){
R int v=to[i];
if(v==1&&(u&bit)==panduan) continue;
if(dis[v]>dis[u]+w[i]){
dis[v]=dis[u]+w[i];
if(!in[v]) push(v),in[v]=1;
}
}
}
return dis[1];
}
inline void add(int x,int y,int z){
to[++tot]=y;w[tot]=z;
nex[tot]=fir[x];fir[x]=tot;
}
int work(){
R int ret=0x3f3f3f3f;
R int tmp=0;int nn=n;
while(nn) tmp++,nn>>=1;
for(R int i=0;i<tmp;i++)
{ret=std::min(ret,dij(1<<i,1<<i)),ret=std::min(ret,dij(1<<i,0));}
return ret;
}
int main(){
n=read();m=read();
for(R int i=1;i<=m;i++){
int x=read(),y=read(),ww=read(),www=read();
add(x,y,ww);add(y,x,www);
}
R int ret=work();
std::printf("%d",ret==0x3f3f3f3f?-1:ret);
return 0;
}

题解 bzoj 4398福慧双修(二进制分组)的更多相关文章

  1. bzoj 4398 福慧双修——二进制分组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可.最短路不会重复经过一条边. ...

  2. bzoj 4398 福慧双修 —— 二进制分组+多起点最短路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ...

  3. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  4. BZOJ 4140 凸包+二进制分组

    思路: $(x_0-x)^2+(y_0-y)^2<=x^2+y^2$ $y>=(-x_0/y_0)x+(x_0^2+y_0^2)/2y0$ 这显然就是凸包了 以一个斜率不断向下(上)走   ...

  5. 【技巧 二进制分组】bzoj4398: 福慧双修&&2407: 探险

    二进制分组也可以说是一种比较优美的拆贡献方式吧? Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅 ...

  6. 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

    [BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...

  7. 【BZOJ4140】共点圆加强版(二进制分组)

    [BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ...

  8. 【BZOJ2989】数列(二进制分组,主席树)

    [BZOJ2989]数列(二进制分组,主席树) 题面 BZOJ 权限题啊... Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即g ...

  9. 【CF710F】String Set Queries(二进制分组,AC自动机)

    [CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ...

随机推荐

  1. (js描述的)数据结构[栈结构](2)

    (js描述的)数据结构[栈结构](2) 一.什么是栈结构 1.一种受限制的线性结构,这种结构可以基于数组来实现. 2.可以抽象成一个容器,上面的是栈顶,底下的是栈底.所以仅允许对栈顶进行操作, 二.栈 ...

  2. 002-IDE的使用与数据类型-C语言笔记

    002-IDE的使用与数据类型-C语言笔记 学习目标 1.[了解]IDE并熟悉Xcode基本使用技巧 2.[理解]C程序的入口和运行流程 3.[理解]变量的声明赋值和一些细节 4.[理解]变量的命名规 ...

  3. Extjs——简单的Grid panel小实例

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  4. PDM添加唯一性约束

  5. stand up meeting 11/25/2015 暨sprint2总结

    今天在课堂上进行了小组项目的阶段性总结,这两天小组内也是频繁的开会,具体细节我们已经反复核查,具体不表~ sprint2个人工作总结: 冯晓云:完成了必应词典在线查词api的调用和网络状况的检测:完成 ...

  6. 快速搭建网站信息库(小型Zoomeye)

    前言:本来是不想重复造车轮的,网上资料有开源的fofa,和一些设计.有的架设太复杂了,好用东西不会用,整个毛线.还有的没有完整代码. 设计方案:    测试平台:windows    测试环境:php ...

  7. 《并发编程的艺术》阅读笔记之Sychronized

    概述 在JDK1.6中,锁一共四种状态,级别由低到高依次是:无锁状态.偏向锁状态.轻量级锁状态和重量级锁状态.锁可以升级但不能降级,这是为了提高获得锁和释放锁的效率.只有重量级锁涉及到操作系统线程切换 ...

  8. JSP中引用CSS样式文件却无法显示的问题解决方案

    你也遇到过这种问题吗,CSS写好了,JSP写好了,在JSP中调用CSS文件,路径检查后也正确,但是无法显示渲染后的页面 原因:罪魁祸首就是过滤器响应数据的时候,响应头设置为了“text/html”,但 ...

  9. 白话理解https

    为什么需要加密? 因为http的内容是明文传输的,传输过程有可能被劫持或被篡改(中间人攻击),如何解决? 当然是加密.最简单的方式就是对称加密(快). 对称机密 就是一个密钥,可以理解为一把钥匙,我们 ...

  10. Service Mesh 介绍

    传统单体应用的局限性说明 传统单体应用代码体量庞大繁杂,不利于理解,也不利于团队合作开发,更不利于频繁更新和部署,增加服务宕机的风险. 耦合性高,功能代码块之前很容易造成强依赖,只要其中任何一个代码逻 ...