bzoj#2407-探险【最短路,二进制分组】
正题
题目链接:https://darkbzoj.tk/problem/2407
题目大意
\(n\)个点的一张无向图(但是正反权值不同),求一个从\(1\)出发回到\(1\)且不经过重复边的最短路径。
\(1\leq n\leq 10000,1\leq m\leq 2\times 10^5\)
解题思路
考虑一个暴力的做法,枚举一条出边枚举一条入边,然后求出去的点到入点的最短路。
但是这样如果点\(1\)度数很多就会\(T\)。
但是这种问题配最短路是很经典的套路,因为两个不同的数字至少有一个二进制位不同,所以我们可以枚举一个二进制位,然后这个位为\(1\)的当出边,为\(0\)的当入边就好了。
时间复杂度\(O((n+m)\log^2 m)\)
code
#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=11000;
struct node{
int to,next,w,id,ban;
}a[N*40];
int n,m,tot,ans,ls[N],f[N];bool v[N];
priority_queue<pair<int,int> > q;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline int read()
{
char c;int d=1;int f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
void addl(int x,int y,int w,int id){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;a[tot].w=w;
a[tot].id=id;
return;
}
void dij(){
memset(f,0x3f,sizeof(f));
memset(v,0,sizeof(v));
q.push(mp(0,1));f[1]=0;
while(!q.empty()){
int x=q.top().second;q.pop();
if(v[x])continue;v[x]=1;
for(int i=ls[x];i;i=a[i].next){
if(a[i].ban)continue;
int y=a[i].to;
if(f[x]+a[i].w<f[y]){
f[y]=f[x]+a[i].w;
q.push(mp(-f[y],y));
}
}
}
return;
}
int main()
{
tot=1;n=read();m=read();
for(int i=1;i<=m;i++){
int x=read(),y=read(),w=read(),v=read();
addl(x,y,w,i);addl(y,x,v,i);
}
ans=2147483647;
for(int p=0;p<18;p++){
for(int i=2;i<=tot;i++)
if((a[i].id>>p)&1)a[i].ban=(a[i].to==1);
else a[i].ban=(a[i^1].to==1);
dij();
for(int i=2;i<=tot;i++)
if(!a[i].ban&&a[i].to==1)
ans=min(ans,f[a[i^1].to]+a[i].w);
}
printf("%d\n",ans);
return 0;
}
bzoj#2407-探险【最短路,二进制分组】的更多相关文章
- HDU - 6166:Senior Pan(顶点集合最短路&二进制分组)
Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory pro ...
- hdu-6166(最短路+二进制分组)
题意:给你n个点m条边的有向图,然后再给你k个不同的点,问你这k个点的最小距离: 解题思路:这道题最需要注意的就是k个点一定是不同的,那么有一个结论就是任意两个不同的数字中,在他们的二进制地表示中,一 ...
- 【刷题】BZOJ 2407 探险
Description 探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过! 比赛即将开始,工作人员说明了这次比赛的规则: ...
- [bzoj4398] 福慧双修 最短路 二进制分组
---题面--- 题解: 考场上看的这道题,,,当时70分算法打挂了,今天才知道这个也是原题.... 首先,对于不跟1相邻的边,肯定不会经过两次,因为经过两次就回来了,除了增加路径长度之外没有任何意义 ...
- 【技巧 二进制分组】bzoj4398: 福慧双修&&2407: 探险
二进制分组也可以说是一种比较优美的拆贡献方式吧? Description 菩萨为行,福慧双修,智人得果,不忘其本.——唐朠立<大慈恩寺三藏法师传>有才而知进退,福慧双修,这才难得.——乌雅 ...
- 题解 bzoj 4398福慧双修(二进制分组)
二进制分组,算个小技巧 bzoj 4398福慧双修 给一张图,同一条边不同方向权值不同,一条边只能走一次,求从1号点出发再回到1号点的最短路 一开始没注意一条边只能走一次这个限制,打了个从一号点相邻节 ...
- HDU 6166 Senior Pan(二进制分组+最短路)
题意 给出一个\(n\)个点\(m\)条边的有向图\((n,m<=100000)\),从中选择\(k\)个点\((k<=n)\),问这k个点两两之间的最短路最小值是多少? 思路 直接的想法 ...
- bzoj 4398 福慧双修——二进制分组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可.最短路不会重复经过一条边. ...
- HDU 6166 Senior Pan(多校第九场 二进制分组最短路)
题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点 ...
随机推荐
- HCNP Routing&Switching之OSPF网络类型
前文我们了解了PPPoE协议相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15182512.html:今天我们聊聊一聊OSPF中的网络类型相关话题: ...
- SQL Server中的distinct(不允许重复)
参考网址:https://blog.csdn.net/tswc_byy/article/details/81835023 一.建库和建表create database scortuse scortcr ...
- 【springboot】集成swagger
1.简介 本章介绍 SpringBoot2.1.9 集成 Swagger2 生成在线的API接口文档. 2. pom依赖: 通过对比了swagger的几个版本,发现还是2.6.1问题最少 <!- ...
- layui关闭弹出框
layer.close(index) - 关闭特定层 //当你想关闭当前页的某个层时 var index = layer.open(); var index = layer.alert(); var ...
- 如何用Mybatis逆向工程实现分页查询(更改生成的Example)
如何用Mybatis逆向工程实现分页查询 一个很简单的方法,如果要mysql实现分页查询的话,执行下述语句即可 select * from table limit (offset)5,(limit) ...
- Flink中的Time与Window
一.Time 在Flink的流式处理中,会涉及到时间的不同概念 Event Time(事件时间):是事件创建的时间.它通常由事件中的时间戳描述,例如采集的日志数据中,每一条日志都会记录自己的生成时间, ...
- CNN的Pytorch实现(LeNet)
CNN的Pytorch实现(LeNet) 上次写了一篇CNN的详解,可是累坏了老僧我.写完后拿给朋友看,朋友说你这Pytorch的实现方式对于新人来讲会很不友好,然后反问我说里面所有的细节你都明白 ...
- SpringBoot博客开发之AOP日志处理
日志处理: 需求分析 日志处理需要记录的是: 请求的URL 访问者IP 调用的方法 传入的参数 返回的内容 上面的内容要求在控制台和日志中输出. 在学习这部分知识的时候,真的感觉收获很多,在之前Spr ...
- 读《深入理解java虚拟机》小结
之所以学习 jvm ,是因为在学习多线程相关知识时,对 volatile 关键字理解的不够透彻,总有种似懂非懂的感觉.于是通过在网上各种资料的查阅,最终将 volatile 和 jvm 联系上了,本身 ...
- linux 查看用户密码
2021-07-26 1.查看前三个密码 head -3 / etc / passwd # 注解 /etc/passwd 中一行记录对应着一个用户,每行记录又被冒号 (:) 分隔为 7 个字段,其格式 ...