题解 bzoj 4398福慧双修(二进制分组)
二进制分组,算个小技巧
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福慧双修(二进制分组)的更多相关文章
- bzoj 4398 福慧双修——二进制分组
		题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可.最短路不会重复经过一条边. ... 
- bzoj 4398 福慧双修 —— 二进制分组+多起点最短路
		题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ... 
- [BZOJ 2989]数列(二进制分组+主席树)
		[BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ... 
- 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$ 这显然就是凸包了 以一个斜率不断向下(上)走 ... 
- 【技巧  二进制分组】bzoj4398: 福慧双修&&2407: 探险
		二进制分组也可以说是一种比较优美的拆贡献方式吧? Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅 ... 
- 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
		[BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ... 
- 【BZOJ4140】共点圆加强版(二进制分组)
		[BZOJ4140]共点圆加强版(二进制分组) 题面 BZOJ 题解 我卡精度卡了一天.... 之前不强制在线的做法是\(CDQ\)分治,维护一个凸壳就好了. 现在改成二进制分组,每次重建凸壳就好了. ... 
- 【BZOJ2989】数列(二进制分组,主席树)
		[BZOJ2989]数列(二进制分组,主席树) 题面 BZOJ 权限题啊... Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即g ... 
- 【CF710F】String Set Queries(二进制分组,AC自动机)
		[CF710F]String Set Queries(二进制分组,AC自动机) 题面 洛谷 CF 翻译: 你有一个字符集合\(D\),初始为空, 有三种操作: 往\(D\)中加入一个串:从\(D\)中 ... 
随机推荐
- IDEA使用技巧,如何在JSP中创建Servlet“小程序”
			步骤 1.新建一个java类,实现Servlet接口 2.实现接口中的抽象方法: 3.在web.xml文件中配置好servlet <web-app ......> <servlet& ... 
- Java 方法 的使用
			简单的说: 方法就是完成特定功能的代码块– 在很多语言里面都有函数的定义– 函数在Java中被称为方法 • 格式:– 修饰符 返回值类型 方法名(参数类型 参数名1, 参数类型参数名2…) {函数体; ... 
- Python设计模式(10)-模板模式
			class DbManager: def insert(self): pass def dele(self): pass class DbManager: def insert(self): pass ... 
- 06-jmeter参数化(函数对话框使用)
			概念: 1.变量命名的规则:字母.下划线开头,可包含数字,严格区分大小写 2.配置元件:用户定义的变量-------值是不变化的 用户命名的参数--------可以动态获取的并传参的 jmeter函数 ... 
- loadrunner vuser 限制修改
- 004-流程控制-C语言笔记
			004-流程控制-C语言笔记 学习目标 1.[掌握]关系运算符和关系表达式 2.[掌握]逻辑运算符和逻辑表达式 3.[掌握]运算符的优先级和结合性 4.[掌握]if-else if-else结构的使用 ... 
- python批量爬取动漫免费看!!
			实现效果 运行环境 IDE VS2019 Python3.7 Chrome.ChromeDriver Chrome和ChromeDriver的版本需要相互对应 先上代码,代码非常简短,包含空行也才50 ... 
- 基础_TCP/IP
			概念明确: 1:TCP/IP代表传输控制协议/网际协议,指的是一系列协议 为什么会叫TCP/IP.因为用的多, 2:HTTP 是属于应用层的协议 3:OSI七层模型和TCP/IP 平等,只是TCP/ ... 
- JMeter在Mac下的安装
			其实不论操作系统是Windows.Unix(如Mac OS).Linux(如Ubuntu)等,JMeter所需要的基础环境配置都是类似的,本文介绍JMeter for MAC的安装与环境配置. JMe ... 
- Redis的三大问题
			一般我们对缓存读操作的时候有这么一个固定的套路: 如果我们的数据在缓存里边有,那么就直接取缓存的. 如果缓存里没有我们想要的数据,我们会先去查询数据库,然后将数据库查出来的数据写到缓存中. 最后将数据 ... 
