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+5,M=1e5+5,K=20; int n,m,mx,hd[N],xnt=1,to[M<<1],nxt[M<<1],w[M<<1]; 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=0;bool fx=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',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>>=1,mx++;mx--;bin[0]=1;for(int i=1;i<=mx;i++)bin[i]=bin[i-1]<<1; } void dj() {memset(vis,0,sizeof vis);while(q.size()){int k=q.top().second;q.pop();if(vis[k])continue;vis[k]=1;for(int i=hd[k],v;i;i=nxt[i])if(!use[i>>1]&&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[1]); } int main() {n=rdn(); m=rdn(); init();for(int i=1,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[1];i;i=nxt[i])sta[++top]=i;for(int i=0;i<=mx;i++){memset(dis,0x3f,sizeof dis);for(int j=1;j<=top;j++){int k=sta[j];if(!(to[k]&bin[i])){q.push(make_pair(-w[k],to[k]));use[k>>1]=1;dis[to[k]]=w[k];}}dj();memset(dis,0x3f,sizeof dis);for(int j=1;j<=top;j++){int k=sta[j];if(to[k]&bin[i]){q.push(make_pair(-w[k],to[k]));use[k>>1]=1;dis[to[k]]=w[k];}else use[k>>1]=0;}dj();for(int j=1;j<=top;j++)if(to[sta[j]]&bin[i])use[sta[j]>>1]=0;}printf("%d\n",ans==1e9?-1:ans);return 0; }
转载于:https://www.cnblogs.com/Narh/p/9795835.html
bzoj 4398 福慧双修——二进制分组相关推荐
- bzoj 4398 福慧双修 —— 二进制分组+多起点最短路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ...
- BZOJ 2407: 探险/BZOJ 4398: 福慧双修 dijkstra 构造
2407: 探险 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 170 Solved: 95 [Submit][Status][Discuss] ...
- bzoj 4398 福慧双修 题解
卡了一晚上啊 首先我们要跑一边整张图的spfa,记录每个点是从哪条边出去的(pre数组) 这里记录的不是前驱边,而是和原点相连的第一个点编号,因为不能走重复边所以才要记录这个,以免刚刚出去又原路返回 ...
- bzoj 4398: 福慧双修(最短路建模/构造)
简述题意: 给定一个有向图,对于连接同两个点的边算作同一条,问不经过重复边的最小正权环. 保证没有重边(这个是指有向的),没有自环. 算法:最短路+构造 难度:NOIP+ 题解: 有一种暴力的思路,感 ...
- 【技巧 二进制分组】bzoj4398: 福慧双修2407: 探险
二进制分组也可以说是一种比较优美的拆贡献方式吧? Description 菩萨为行,福慧双修,智人得果,不忘其本. --唐朠立<大慈恩寺三藏法师传> 有才而知进退,福慧双修,这才难得. - ...
- BZOJ4398: 福慧双修【二进制分组+最短路】
4398: 福慧双修 考虑笨蛋,我们可以枚举出边,然后Dij就可以了. 显然在菊花图的情况下要T 我们考虑分组,对于连1的边,一半强制为出边,一半强制为入边,跑DIJ,然后交换,再做一遍. 然后继续分 ...
- 【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
[BZOJ3821/UOJ46]玄学(二进制分组,线段树) 题面 BZOJ UOJ 题解 呜,很好的题目啊QwQ. 离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接 ...
- bzoj29894170数列——二进制分组+主席树
题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...
- 【BZOJ2069】ZAW(POI2004)-最短路+二进制分组
测试地址:ZAW 题目大意: 给定一张边是双向的图,一条边走不同的方向可能代价不同,代价都非负,求从点111出发,不经过重复的点或边的最小回路.n≤5000,m≤10000n\le 5000,m\le ...
最新文章
- JavaWeb--过滤器
- javaweb学习总结二十五(response对象的用法一)
- [ImportNew]Java中的Timer类和TimerTask类
- java 中的this
- 6-2 多项式求值 (15 分)
- 2018-2019-1 20165234 《信息安全系统设计基础》第八周学习总结
- Standard C++ Episode 10
- a + b + c 求和
- python 自动下载文件_【Py大法系列--03】Python如何自动下载文件
- OpenCV-获取图像中圆线上的数据
- 计算机网络-扩展路由器网段
- kubunetes packages.cloud.google.com gpg:no valid OpenPGP data found
- JxBrowser 7.15 for java Crack
- 关于金融学和计量金融学的好书
- vue和 element ui下载到本地后引入
- 简单了解计算机组成原理 -- CPU与操作系统
- 机器学习(三):线性模型
- Linux 的目录树
- jsp文件的上传与下载
- HTML -JavaScript--模拟病毒