Description

在Byte山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是一条笔直通向“前面洞口”的道路. 隧道互相都不交叉(他们只在洞室相遇). 两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决定组织办一个'King's of Byteotia Cup' 比赛. 参赛者的目标就是任意选择一条路径进入洞穴并尽快出来即可. 一条路径必须经过除了“前面洞口”之外还至少要经过其他一个洞室.一条路径中一个洞不能重复经过(除了“前面洞室”以外),类似的一条隧道也不能重复经过. 一个著名的洞穴探险家 Byteala 正准备参加这个比赛. Byteala 已经训练了数月而且他已获得了洞穴系统的一套详细资料. 对于每条隧道他都详细计算了从两个方向经过所需要的时间. 经过一个洞室的时间很短可以忽略不记. 现在Byteala 向计算一条符合条件的最优路径.

Input

第一行有两个数n 和 m (3 <= n <= 5000, 3 <= m <= 10000) 分别表示洞室的数目以及连接他们的隧道的数目. 洞室从1 到 n编号. “前面洞室”的编号为1. 接下来m 行描述了所有的隧道. 每行四个整数a,b,c,d 表示从洞室a到洞室b需要c分钟的时间,而从洞室b到洞室a需要d分钟的时间, 1 <= a,b <= n, a <> b, 1 <= c,d <= 10000. 你可以假设符合要求的路径肯定存在.

Output

输出一行,最少需要多少时间完成比赛.

Sample Input

3 3

1 2 4 3

2 3 4 2

1 3 1 1

Sample Output

6

Solution

这是一个假二进制分组

对一号点相连的点按照二进制来分组

枚举二进制,一种只能由1走向它,另一种只能由它走向1

然后每次都跑一边Dijkstra就好了

因为任意两个点一定在一个数的二进制中在不同的分组,所以方案经过的两个点一定会被枚举到

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define ft first
#define sd second
#define pb(a) push_back(a)
#define mp(a,b) std::make_pair(a,b)
#define ITR(a,b) for(auto a:b)
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=10000+10,MAXM=200000+10,inf=0x3f3f3f3f;
int n,m,e,beg[MAXN],nex[MAXM<<1],to[MAXM<<1],was[MAXM<<1],d[MAXN],dir[MAXN],ans=inf;
std::priority_queue< std::pair<int,int>,std::vector< std::pair<int,int> >,std::greater< std::pair<int,int> > > q;
namespace IO{const int Buffsize=1<<15,Output=1<<24;static char Ch[Buffsize],*S=Ch,*T=Ch;inline char getc(){return((S==T)&&(T=(S=Ch)+fread(Ch,1,Buffsize,stdin),S==T)?0:*S++);}static char Out[Output],*nowps=Out;inline void flush(){fwrite(Out,1,nowps-Out,stdout);nowps=Out;}template<typename T>inline void read(T&x){x=0;static char ch;T f=1;for(ch=getc();!isdigit(ch);ch=getc())if(ch=='-')f=-1;for(;isdigit(ch);ch=getc())x=x*10+(ch-'0');x*=f;}template<typename T>inline void write(T x,char ch='\n'){if(!x)*nowps++='0';if(x<0)*nowps++='-',x=-x;static int sta[111],tp;for(tp=0;x;x/=10)sta[++tp]=x%10;for(;tp;*nowps++=sta[tp--]^48);*nowps++=ch;}
}
using namespace IO;
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y,int z)
{to[++e]=y;nex[e]=beg[x];beg[x]=e;was[e]=z;
}
inline void Dijstra(int s)
{memset(d,inf,sizeof(d));d[s]=0;q.push(mp(d[s],s));while(!q.empty()){std::pair<int,int> pr=q.top();q.pop();if(pr.ft!=d[pr.sd])continue;int x=pr.sd;for(register int i=beg[x];i;i=nex[i])if(to[i]==1){if(dir[x])continue;if(d[n+1]>d[x]+was[i])d[n+1]=d[x]+was[i];}else{if(x==1&&!dir[to[i]])continue;if(d[to[i]]>d[x]+was[i])d[to[i]]=d[x]+was[i],q.push(mp(d[to[i]],to[i]));}}
}
inline void solve(int ps)
{for(register int i=beg[1];i;i=nex[i])dir[to[i]]=(to[i]>>ps)&1;Dijstra(1);chkmin(ans,d[n+1]);for(register int i=beg[1];i;i=nex[i])dir[to[i]]^=1;Dijstra(1);chkmin(ans,d[n+1]);
}
int main()
{read(n);read(m);REP(i,1,m){int u,v,w1,w2;read(u);read(v);read(w1);read(w2);insert(u,v,w1);insert(v,u,w2);}REP(i,0,13)solve(i);write(ans,'\n');flush();return 0;
}

转载于:https://www.cnblogs.com/hongyj/p/10088169.html

【刷题】BZOJ 2069 [POI2004]ZAW相关推荐

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

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

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

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

  3. BZOJ 2069 POI2004 ZAW 堆优化Dijkstra

    题目大意:给定一张无向图,每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路 显然我们需要从点1出发走到某个和点1相邻的点上,然后沿最短路走到另一个和点1相邻 ...

  4. 2069: [POI2004]ZAW

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

  5. bzoj 2096 [POI2004]ZAW——二进制枚举

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2069 可以把直接相连的点分成  从1点出的一部分  和  走向1点的一部分.多起点最短路就和 ...

  6. BZOJ 2135 刷题计划(贪心,求导,二分)【BZOJ 修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2135 是 hydro 的 BZOJ ...

  7. 【刷题】BZOJ 4176 Lucas的数论

    Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目"求Sigma(f(i)),其中1<=i< ...

  8. BZOJ刷题记录---提高组难度

    BZOJ刷题记录---提高组难度 总目录详见https://blog.csdn.net/mrcrack/article/details/90228694 序号 题号 算法 思想难度 实现难度 总难度 ...

  9. BZOJ第一页刷题计划

    BZOJ第一页刷题计划 已完成:67 / 90 [BZOJ1000]A+B Problem:A+B: [BZOJ1001][BeiJing2006]狼抓兔子:最小割: [BZOJ1002][FJOI2 ...

最新文章

  1. C++中#error/assert/static_assert的区别及使用
  2. AngularJS 实现的输入自动完成补充功能
  3. AMD与intel CPU型号大全(接口)
  4. webservice-概念性学习(一)
  5. 深入分析 Java I/O 的工作机制--转载
  6. python输入半径计算公式_Python:09设计Circle类包括圆心半径、颜色属性,编写类方法计算周长与面积(2种方法)...
  7. Linux的Nginx三:类型|特点
  8. HDU3509(构造矩阵)
  9. PyQt中从RAM新建QIcon对象 / Create a QIcon from binary data
  10. 分析.cpp文件编译生成的汇编文件里语句的作用
  11. Flutter设置允许HTTP访问
  12. 你不得不知道的通信行业基础介绍
  13. c语言如何输出数组最大值和最小值,C语言输出数组中最大和次大的数
  14. 计算机组装维护安装光驱步骤,光驱怎么安装?教你如何正确安装光驱方法
  15. python如何获取网页内容_python如何获取网页内容
  16. 网友发现Q版西游:唐僧师徒脸谱上50元人民币
  17. Android开发技巧——Camera拍照功能
  18. python大数据技术_大数据技术python
  19. 阿里CTO程立:科技公司的技术创新和责任担当
  20. (三十三 :2021.01.12)MICCAI 2016 追踪之论文纲要

热门文章

  1. HTML文档中注释标记作用,html的注释有什么作用
  2. 中文字符 简体繁体相互转换
  3. 英文pdf的划词翻译阅读方法
  4. 中标麒麟B040版本桌面系统root密码破解
  5. 增加平均订单价值 – 交叉销售VS.升级销售
  6. idea 亮度 调整_如何设置显示屏幕的亮度
  7. NFC开发 —————实用工具以及开发文档(四)
  8. httprunner之业务解耦
  9. ssm+Vue计算机毕业设计学科竞赛赛场安排系统(程序+LW文档)
  10. 神奇的 ViewDragHelper,让你轻松定制拥有拖拽能力的 ViewGroup