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;
}

【刷题】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 2407 探险

    Description 探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过! 比赛即将开始,工作人员说明了这次比赛的规则: ...

  7. BZOJ2069: [POI2004]ZAW

    2069: [POI2004]ZAW Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 303  Solved: 138[Submit][Status][D ...

  8. 【刷题】BZOJ 4543 [POI2014]Hotel加强版

    Description 同OJ3522 数据范围:n<=100000 Solution dp的设计见[刷题]BZOJ 3522 [Poi2014]Hotel 然后发现dp的第二维与深度有关,于是 ...

  9. 【刷题】BZOJ 4316 小C的独立集

    Description 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使 ...

随机推荐

  1. python 取值方法:截取字符串

    截取最后三位:aa=“TFR20171230001-1”cc=aa[-3]+aa[-2]+aa[-1] aa="1.36x36.8-ddr" bb=aa.split('x')[1] ...

  2. HSF源码阅读

    HSF各组成之间的关系 1 服务提供者注册与发布 <bean id="hsfTestService" class="com.test.service.impl.Hs ...

  3. Vue2.0 搭配 axios

    1.安装axios $ npm install axios 2.Demo (1)Get // 为给定 ID 的 user 创建请求 axios.get('/user?ID=12345') .then( ...

  4. Canary机制的绕过

    目标程序下载 提取码:8ypi 1.检查程序开启了哪些安全保护机制 Canary与NX开启了 Canary机制简介 64位的canary机制,会在函数头部添加: mov rax,QWORD PTR f ...

  5. Supervisor (进程管理利器) 使用说明 - 运维笔记

    一.Supervisor简单介绍supervisor是一个 Client/Server模式的系统,允许用户在类unix操作系统上监视和控制多个进程,或者可以说是多个程序.supervisor与laun ...

  6. oracle数据恢复方法

    https://www.cnblogs.com/hqbhonker/p/3977200.html

  7. C. Ehab and a 2-operation task

    链接 [https://codeforces.com/contest/1088/problem/C] 题意 n个数,最多n+1操作,要么前i个数加x,要么前i个数对x取余,最后使得严格递增 分析 直接 ...

  8. Week 3 结对编程

    Group: 杜正远 潘礼鹏 结对编程: 优点: 集体荣誉感.你们已经是一个集体了,一定得为对方着想负责. 1.看对方的代码,彼此会互相学习到一些奇妙的方法. 2.结对编程能把两个事情分开,降低复杂度 ...

  9. 软件项目第一次sprint评论

    软件项目第一次sprint评论 组名:天线宝宝四人组                                   姓名:高长志 1. 组名:9-652组 项目:炸弹人游戏 对于炸弹人游戏,首先 ...

  10. Zookeeper 3.4.8分布式安装

    1.机器信息 五台centos 64位机器 2.集群规划 Server Name Hadoop Cluster Zookeeper   Ensemble HBase Cluster Hadoop01 ...