bzoj 4398 福慧双修——二进制分组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398
如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可。最短路不会重复经过一条边。
怎样枚举较优?需要枚举到答案的起点在一组、终点在另一组;考虑按点的编号二进制分组,即枚举每一位,为0的在一组,为1的在另一组。
因为两个点编号不同,所以二进制表示至少有1位不同,即任意两个点一定一度被分到过两个组里。
好像还有构造新图的更快的做法。不过也没管。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=4e4+,M=1e5+,K=;
int n,m,mx,hd[N],xnt=,to[M<<],nxt[M<<],w[M<<];
int dis[N],sta[N],top,ans=1e9,bin[K];
bool vis[N],use[M];
priority_queue<pair<int,int> >q;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return fx?ret:-ret;
}
void add(int x,int y,int z)
{
to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;
}
void init()
{
int k=n;while(k)k>>=,mx++;mx--;
bin[]=;for(int i=;i<=mx;i++)bin[i]=bin[i-]<<;
}
void dj()
{
memset(vis,,sizeof vis);
while(q.size())
{
int k=q.top().second;q.pop();
if(vis[k])continue;vis[k]=;
for(int i=hd[k],v;i;i=nxt[i])
if(!use[i>>]&&dis[v=to[i]]>dis[k]+w[i])
{
dis[v]=dis[k]+w[i];
q.push(make_pair(-dis[v],v));
}
}
ans=min(ans,dis[]);
}
int main()
{
n=rdn(); m=rdn(); init();
for(int i=,u,v,z1,z2;i<=m;i++)
{
u=rdn();v=rdn();z1=rdn();z2=rdn();
add(u,v,z1);add(v,u,z2);
}
for(int i=hd[];i;i=nxt[i])sta[++top]=i;
for(int i=;i<=mx;i++)
{
memset(dis,0x3f,sizeof dis);
for(int j=;j<=top;j++)
{
int k=sta[j];
if(!(to[k]&bin[i]))
{
q.push(make_pair(-w[k],to[k]));use[k>>]=;
dis[to[k]]=w[k];
}
}
dj();
memset(dis,0x3f,sizeof dis);
for(int j=;j<=top;j++)
{
int k=sta[j];
if(to[k]&bin[i])
{
q.push(make_pair(-w[k],to[k]));use[k>>]=;
dis[to[k]]=w[k];
}
else use[k>>]=;
}
dj();
for(int j=;j<=top;j++)
if(to[sta[j]]&bin[i])use[sta[j]>>]=;
}
printf("%d\n",ans==1e9?-:ans);
return ;
}
bzoj 4398 福慧双修——二进制分组的更多相关文章
- bzoj 4398 福慧双修 —— 二进制分组+多起点最短路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ...
- 题解 bzoj 4398福慧双修(二进制分组)
二进制分组,算个小技巧 bzoj 4398福慧双修 给一张图,同一条边不同方向权值不同,一条边只能走一次,求从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 ...
- 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组
F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...
随机推荐
- How to set the initial value of a select element using AngularJS ng-options & track by
原文: https://www.gurustop.net/blog/2014/01/28/common-problems-and-solutions-when-using-select-element ...
- Android API Guides---Services
服务 在该文献 基础 声明在清单服务 创建一个启动的服务 扩展IntentService类 扩展服务类 启动服务 停止服务 创建绑定服务 将通知发送给用户 执行在前台服务 管理服务生命周期 实施生命周 ...
- Go语言阅读小笔记,来自知呼达达关于unsafe.Pointer的分享.
第一式 - 获得Slice和String的内存数据 func stringPointer(s string) unsafe.Pointer { p := (*reflect.StringHeader) ...
- uva 1378 - A Funny Stone Game sg博弈
题意:David 玩一个石子游戏. 游戏中,有n堆石子,被编号为0..n-1.两名玩家轮流取石子. 每一轮游戏.每名玩家选取3堆石子i,j,k(i<j,j<=k,且至少有一枚石子在第i堆石 ...
- Asp.Net初学小结 判断数组中是否有重复的数据
Asp.Net初学小结 第一章 1.搭建Asp.net开发环境 1).net FrameWork(VS) 2)IIS(xp:5.1,2003:6.0,vista:70,win7:7.5) ...
- linux find prune排除某目录或文件
http://blog.csdn.net/ysdaniel/article/details/7995681 查找cache目录下不是html的文件 find ./cache ! -name '*.ht ...
- 内核顶层Makefile相关1
http://www.groad.net/bbs/simple/?f104.htm $(Q) 变量 内核 Makefile 文件 238 行到 259 行的注释中知道,$(Q) 变量的作用是决定是否在 ...
- Win10升级.NET Framework 3.5或2.0遇到错误0x800f081f
具体方法如下: 1.将WIN10安装光盘ISO文件加载到虚拟光驱中. 2.WIN键+R键一起按,输入CMD后回车. 3.在CMD的命令行窗口里输入: cd C:Windowssystem32 跳转到s ...
- 配置tomcat,访问端口改为80
首先:找到tomcat的的config文件夹下的server.xml文件: 编辑server.xml 保存server.xml文件,重启tomcat服务器,即可. 亲测好使.
- Windows10搭建FTP服务器
配置FTP服务器步骤: 第一步: 打开控制面板--->选择程序--->启动或关闭Windows功能--->勾选FTP服务器等.如下图: 第二步: 右键此电脑--->点击管理-- ...