题目: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 福慧双修——二进制分组相关推荐

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

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

  2. BZOJ 2407: 探险/BZOJ 4398: 福慧双修 dijkstra 构造

    2407: 探险 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 170  Solved: 95 [Submit][Status][Discuss] ...

  3. bzoj 4398 福慧双修 题解

    卡了一晚上啊 首先我们要跑一边整张图的spfa,记录每个点是从哪条边出去的(pre数组) 这里记录的不是前驱边,而是和原点相连的第一个点编号,因为不能走重复边所以才要记录这个,以免刚刚出去又原路返回 ...

  4. bzoj 4398: 福慧双修(最短路建模/构造)

    简述题意: 给定一个有向图,对于连接同两个点的边算作同一条,问不经过重复边的最小正权环. 保证没有重边(这个是指有向的),没有自环. 算法:最短路+构造 难度:NOIP+ 题解: 有一种暴力的思路,感 ...

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

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

  6. BZOJ4398: 福慧双修【二进制分组+最短路】

    4398: 福慧双修 考虑笨蛋,我们可以枚举出边,然后Dij就可以了. 显然在菊花图的情况下要T 我们考虑分组,对于连1的边,一半强制为出边,一半强制为入边,跑DIJ,然后交换,再做一遍. 然后继续分 ...

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

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

  8. bzoj29894170数列——二进制分组+主席树

    题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...

  9. 【BZOJ2069】ZAW(POI2004)-最短路+二进制分组

    测试地址:ZAW 题目大意: 给定一张边是双向的图,一条边走不同的方向可能代价不同,代价都非负,求从点111出发,不经过重复的点或边的最小回路.n≤5000,m≤10000n\le 5000,m\le ...

最新文章

  1. JavaWeb--过滤器
  2. javaweb学习总结二十五(response对象的用法一)
  3. [ImportNew]Java中的Timer类和TimerTask类
  4. java 中的this
  5. 6-2 多项式求值 (15 分)
  6. 2018-2019-1 20165234 《信息安全系统设计基础》第八周学习总结
  7. Standard C++ Episode 10
  8. a + b + c 求和
  9. python 自动下载文件_【Py大法系列--03】Python如何自动下载文件
  10. OpenCV-获取图像中圆线上的数据
  11. 计算机网络-扩展路由器网段
  12. kubunetes packages.cloud.google.com gpg:no valid OpenPGP data found
  13. JxBrowser 7.15 for java Crack
  14. 关于金融学和计量金融学的好书
  15. vue和 element ui下载到本地后引入
  16. 简单了解计算机组成原理 -- CPU与操作系统
  17. 机器学习(三):线性模型
  18. Linux 的目录树
  19. jsp文件的上传与下载
  20. HTML -JavaScript--模拟病毒

热门文章

  1. 智慧政务解决方案-最新全套文件
  2. 2016年10月9日 星期日 --出埃及记 Exodus 18:20
  3. 计算机游戏攻略66 关,一笔画攻略,一笔画攻略66关
  4. 初中计算机的组成试讲教案模板小学语文,初中语文面试试讲教案
  5. 贵州支教之第三天(11月9日)
  6. 常见面试题整理--操作系统篇
  7. SONY新的圈铁耳机
  8. 当下知识付费行业趋势
  9. Http请求之GET,POST,PUT,DELETE方法详解
  10. win11怎么开启任务管理器?