题目大意:给定一张无向图,每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路
显然我们需要从点1出发走到某个和点1相邻的点上,然后沿最短路走到另一个和点1相邻的点上,然后回到点1
那么我们将与点1相邻的点都设为关键点,然后将点1从图中删除,题目转化成了给定图上的一些关键点求最近点对
枚举每个点显然会T
考虑每次将关键点划分为两个集合A,BA,B,然后将AA中的每个点xx的初始距离设为len(1,x)len(1,x),跑最短路,然后用BB中的每个点yy的disy+len(y,1)dis_y+len(y,1)统计答案,再将ABAB反转做一次
这样只要任意点对都被分别划分到两个集合中至少一次,那么答案就被更新完了
如何划分呢?我们考虑按照二进制拆分,对于每一位划分一次,将该位上为00的划分到AA集合中,该位上为11的划分到BB集合中
由于两个数至少有一位不同,因此任意点对至少被划分了一次
这样划分O(log2n)O(log_2n)次就够了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 5050
using namespace std;
struct abcd{int to,f,next;
}table[M<<2];
int head[M],tot;
int n,m,top,ans=0x3f3f3f3f;
pair<int,pair<int,int> >stack[M<<1];
int f[M];
void Add(int x,int y,int z)
{table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;
}
namespace Heap{int heap[M],pos[M],top;void Push_Up(int t){while(t>1){if( f[heap[t]]<f[heap[t>>1]] )swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t>>=1;elsebreak;}}void Insert(int x){heap[++top]=x;pos[x]=top;Push_Up(top);}void Pop(){pos[heap[1]]=0;heap[1]=heap[top--];if(top) pos[heap[1]]=1;int t=2;while(t<=top){if( f[heap[t+1]]<f[heap[t]] )++t;if( f[heap[t]]<f[heap[t>>1]] )swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t<<=1;elsebreak;}}
}
void Dijkstra()
{using namespace Heap;int i;for(i=1;i<=n;i++)Insert(i);while(Heap::top){int x=heap[1];Pop();for(i=head[x];i;i=table[i].next)if(f[table[i].to]>f[x]+table[i].f){f[table[i].to]=f[x]+table[i].f;Push_Up(pos[table[i].to]);}}
}
int main()
{int i,j,x,y,z1,z2;cin>>n>>m;for(i=1;i<=m;i++){scanf("%d%d%d%d",&x,&y,&z1,&z2);if(x>y) swap(x,y),swap(z1,z2);if(x==1)stack[++top]=make_pair(y,make_pair(z1,z2));elseAdd(x,y,z1),Add(y,x,z2);}for(j=1;j<=n;j<<=1){memset(f,0x3f,sizeof f);for(i=1;i<=top;i++)if(i&j)f[stack[i].first]=stack[i].second.first;Dijkstra();for(i=1;i<=top;i++)if(~i&j)ans=min(ans,f[stack[i].first]+stack[i].second.second);memset(f,0x3f,sizeof f);for(i=1;i<=top;i++)if(~i&j)f[stack[i].first]=stack[i].second.first;Dijkstra();for(i=1;i<=top;i++)if(i&j)ans=min(ans,f[stack[i].first]+stack[i].second.second);}cout<<ans<<endl;return 0;
}

BZOJ 2069 POI2004 ZAW 堆优化Dijkstra相关推荐

  1. BZOJ.2069.[POI2004]ZAW(最短路Dijkstra 按位划分)

    题目链接 \(Description\) 给定一张带权图(边是双向的,但不同方向长度不同).求从1出发,至少经过除1外的一个点,再回到1的最短路.点和边不能重复经过. \(n\leq5000,m\le ...

  2. BZOJ 2069: [POI2004]ZAW(Dijkstra + 二进制拆分)

    题意 给定一个有 \(N\) 个点 \(M\) 条边的无向图, 每条无向边 最多只能经过一次 . 对于边 \((u, v)\) , 从 \(u\) 到 \(v\) 的代价为 \(a\) , 从 \(v ...

  3. 【刷题】BZOJ 2069 [POI2004]ZAW

    Description 在Byte山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是一条笔直通向"前面洞口"的道路. 隧道互相都不交叉(他们只在洞室相 ...

  4. bzoj 3040: 最短路(road)(堆优化dijkstra)

    3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MB Submit: 2811  Solved: 933 [Submit][Status][ ...

  5. BZOJ 2118 墨墨的等式 堆优化Dijkstra

    题目大意:给定nn个物品,每个物品有一个非负价值,问[L,R][L,R]区间内有多少价值可以被凑出来 好题!!! 如果物品数量可以为负,显然求个gcdgcd就行了 现在物品数量必须非负 任选一个ai& ...

  6. 2069: [POI2004]ZAW

    2069: [POI2004]ZAW 链接 题意: 给定一张带权图(边是双向的,但不同方向长度不同).求从1出发,至少经过除1外的一个点,再回到1的最短路.点和边不能重复经过. n≤5000,m≤10 ...

  7. 【bzoj5197】[CERC2017]Gambling Guide 期望dp+堆优化Dijkstra

    题目描述 给定一张n个点,m条双向边的无向图. 你要从1号点走到n号点.当你位于x点时,你需要花1元钱,等概率随机地买到与x相邻的一个点的票,只有通过票才能走到其它点. 每当完成一次交易时,你可以选择 ...

  8. HDU1535 Invitation Cards(链式前向星+堆优化dijkstra)[C++]

    目录 题目及翻译 题面 输入 输出 输入样例 输出样例 题目思路 注意事项 AC代码 C++ 题目及翻译 题面 In the age of television, not many people at ...

  9. 【bzoj2259】[Oibh]新型计算机 堆优化Dijkstra

    题目描述 Tim正在摆弄着他设计的"计算机",他认为这台计算机原理很独特,因此利用它可以解决许多难题.  但是,有一个难题他却解决不了,是这台计算机的输入问题.新型计算机的输入也很 ...

最新文章

  1. 《Go并发编程实战》第2版 紧跟Go的1.8版本
  2. 福利 | NVIDIA英伟达免费直播课:带你选择、搭建AI服务器!
  3. faster rcnn源码理解(二)之AnchorTargetLayer(网络中的rpn_data)
  4. android应用案例开发大全_vue.js入门及经典应用案例总结(前端开发必看)
  5. H264 流媒体 编码汇总
  6. python 遍历文件中的文件,文件名
  7. apereo cas开发_Apereo CAS Server服务端搭建教程
  8. gm21模型python_python使用GM11
  9. 容器安全 - 通过SECCOMP过滤在容器中的风险操作
  10. 设计php框架_PHP微型框架设计
  11. java wsimport 调用_Java如何基于wsimport调用wcf接口
  12. CodeIgniter入门
  13. 你在工作中遇到了哪些问题,解决办法是什么
  14. FullCalendar日历控件vue使用记录
  15. 计算机网络技术思维导图Xmind
  16. ANSYS FLUENT 超临界流体物性分段线性插值数据批量导入
  17. 软件架构师需要什么能力?
  18. 7-86 小明的晚饭 (50分)
  19. hbase compact
  20. c++中int a, int *a=new int和 int *a=new int()

热门文章

  1. 简述 MQTT协议概念
  2. [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘
  3. 为什么Lisp如此先进,却永远成为不了编程主流语言?深度解析Lisp的优势与劣势
  4. 什么是对象自身可枚举属性和不可枚举属性
  5. Matlab——报错解决:Robotics Toolbox使用plot()或者teach()机器人报错:索引超出数组元素的数目(4)
  6. 使用stty修改终端设置 stty 用法!
  7. POJ1655 Balancing Act 题解
  8. C语言实现9宫格数独
  9. User must be authenticated with Spring Security before authorization can be completed.解决方法
  10. css鼠标点在文字上背景透明,CSS实现文字半透明显示在图片上方法(示例代码)