bzoj 2069 [ POI 2004 ] ZAW —— 多起点最短路 + 二进制划分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2069
首先,对于和 1 相连的点,一定是从某个点出发,回到另一个点;
所以需要枚举起点和终点,但做 n 遍 dijkstra 不太可行;
可以进行多起点最短路,一次知道了以一些点作为起点、另一些点作为终点的答案;
于是问题是如何划分起点和终点,使一定能找到最优解;
二进制划分,枚举每一位,这一位是 0/1 分成两部分,那么任意不同的两个数一定某一次被分到了不同的集合;
具体做法可以是从 1 出发,不让起点回到 1,不让终点来到 1,最后看看终点的 dis;
也可以干脆去掉 1,起点的 dis 值是从 1 到它的距离;
注意分成两部分后要分别跑一遍是起点和终点的。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const maxn=,maxm=,inf=0x3f3f3f3f;
int n,m,hd[maxn],ct,to[maxm],nxt[maxm],w[maxm],dis[maxn],mx,ans=inf;
int son[maxn],ss,wt[maxn],wc[maxn];
bool vis[maxn],st[maxn],ed[maxn];
priority_queue<pair<int,int> >q;
void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
void dijkstra()
{
while(q.size())q.pop();
memset(vis,,sizeof vis);
memset(dis,0x3f,sizeof dis);
dis[]=; q.push(make_pair(,));
// for(int i=1,x;i<=ss;i++)
// if(st[x=son[i]])dis[x]=wt[x],q.push(make_pair(-dis[x],x));
// vis[1]=1;
while(q.size())
{
int x=q.top().second; q.pop();
if(vis[x])continue; vis[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]]||st[x]&&u==||x==&&ed[u])continue;
// if(vis[u=to[i]])continue;
if(dis[u]>dis[x]+w[i])
dis[u]=dis[x]+w[i],q.push(make_pair(-dis[u],u));
}
}
for(int i=,x;i<=ss;i++)
if(ed[x=son[i]])ans=min(ans,dis[x]+wc[x]);
}
int main()
{
scanf("%d%d",&n,&m);
int tmp=n; while(tmp)mx++,tmp/=;
for(int i=,x,y,a,b;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&a,&b);
add(x,y,a); add(y,x,b);
if(x==)son[++ss]=y,wt[y]=a,wc[y]=b;
if(y==)son[++ss]=x,wt[x]=b,wc[x]=a;
}
for(int i=;i<mx;i++)
{
memset(st,,sizeof st);
memset(ed,,sizeof ed);
for(int j=;j<=ss;j++)
if(son[j]&(<<i))st[son[j]]=;
else ed[son[j]]=;
dijkstra();
for(int j=,x;j<=ss;j++)
if(st[x=son[j]])st[x]=,ed[x]=;
else if(ed[x])ed[x]=,st[x]=;
dijkstra();
}
printf("%d\n",ans);
return ;
}
bzoj 2069 [ POI 2004 ] ZAW —— 多起点最短路 + 二进制划分的更多相关文章
- [POI 2004]ZAW
Description 在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决 ...
- bzoj 2067 [ Poi 2004 ] SZN —— 二分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2067 问题1:贪心考虑,应该是每个点的儿子尽量两两配对,如果剩一个就和自己合并向上,所以 a ...
- bzoj 4398 福慧双修 —— 二进制分组+多起点最短路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ...
- BZOJ 2069: [POI2004]ZAW(Dijkstra + 二进制拆分)
题意 给定一个有 \(N\) 个点 \(M\) 条边的无向图, 每条无向边 最多只能经过一次 . 对于边 \((u, v)\) , 从 \(u\) 到 \(v\) 的代价为 \(a\) , 从 \(v ...
- 【刷题】BZOJ 2069 [POI2004]ZAW
Description 在Byte山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是一条笔直通向"前面洞口"的道路. 隧道互相都不交叉(他们只在洞室相 ...
- BZOJ.2069.[POI2004]ZAW(最短路Dijkstra 按位划分)
题目链接 \(Description\) 给定一张带权图(边是双向的,但不同方向长度不同).求从1出发,至少经过除1外的一个点,再回到1的最短路.点和边不能重复经过. \(n\leq5000,m\le ...
- BZOJ 2069 POI2004 ZAW 堆优化Dijkstra
题目大意:给定一张无向图.每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路 显然我们须要从点1出发走到某个和点1相邻的点上,然后沿最短路走到还有一个和点1相 ...
- [BZOJ 1207] [HNOI 2004] 打鼹鼠 【DP】
题目链接:BZOJ - 1207 题目分析 每一次打鼹鼠一定是从上一次打某只鼹鼠转移过来的,从打第 j 只鼹鼠能不能转移到打第 i 只鼹鼠,算一下曼哈顿距离和时间差就知道了. 那么就有一个 DP ,用 ...
- [BZOJ 3747] [POI 2015] Kinoman【线段树】
Problem Link : BZOJ 3747 题解:ZYF-ZYF 神犇的题解 解题的大致思路是,当区间的右端点向右移动一格时,只有两个区间的左端点对应的答案发生了变化. 从 f[i] + 1 到 ...
随机推荐
- Redis系列(七)--Sentinel哨兵模式
在上一篇文章了解了主从复制,主从复制本身的容错性很差,一旦master挂掉,只能进行手动故障转移,很难完美的解决这个问题 而本文讲解的sentinel可以解决这个问题 Redis sentinel示意 ...
- 微服务网关从零搭建——(三)Ocelot网关 + identity4
增加验证服务 1.创建名为AuthService 的core 空项目 2.修改startup文件 using System; using System.Collections.Generic; usi ...
- BZOJ 5028 小Z的加油店
[题解] 本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数. 那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最 ...
- uva 1444 Knowledge for the masses
uva 1444 Description You are in a library equipped with bookracks that move on rails. There are ma ...
- 如何相互转换逗号分隔的字符串和List --https://blog.csdn.net/yywusuoweile/article/details/50315377
如何相互转换逗号分隔的字符串和List ---https://blog.csdn.net/yywusuoweile/article/details/50315377 方法 2: 利用Guava的Joi ...
- BNUOJ 13358 Binary Apple Tree
Binary Apple Tree Time Limit: 1000ms Memory Limit: 16384KB This problem will be judged on Ural. Orig ...
- noip模拟赛 蒜头君的树
分析:这道题问的是树上整体的答案,当然要从整体上去考虑. 一条边对答案的贡献是这条边一端连接的点的个数*另一端连接的点的个数*边权,可以用一次dfs来统计答案,之后每次更改操作在原答案的基础上增减就好 ...
- 个人常用git命令
最近开始使用git,将自己常用git命令做一个简单归纳,便于记忆. 初始化及配置 git init:初始化资料库 git config --global user.name 'xxx':配置用户名 g ...
- Java中原始数据类型存放位置理解
原始数据类型的变量存放在栈还是堆,应该由上下文去决定. 如下所示的局部方法中,定义了本地变量a,且为原始数据类型,所以存放在栈中. public void func(){ int a = 3; } 再 ...
- 项目中应用到的框架和技术之一——Materialize
一群做C++的老伙计搞前端开发,徒手写html和css应该会折寿..在网上找了半天,Materialize算是用起来很方便的一款前端界面框架.Google的Material Design看起来感觉还是 ...