题目: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 —— 多起点最短路 + 二进制划分的更多相关文章

  1. [POI 2004]ZAW

    Description 在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决 ...

  2. bzoj 2067 [ Poi 2004 ] SZN —— 二分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2067 问题1:贪心考虑,应该是每个点的儿子尽量两两配对,如果剩一个就和自己合并向上,所以 a ...

  3. bzoj 4398 福慧双修 —— 二进制分组+多起点最短路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 按二进制每一位是 0/1 把 1 号点的儿子分成两组,分别作为起点和终点跑多起点最短路 ...

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

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

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

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

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

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

  7. BZOJ 2069 POI2004 ZAW 堆优化Dijkstra

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

  8. [BZOJ 1207] [HNOI 2004] 打鼹鼠 【DP】

    题目链接:BZOJ - 1207 题目分析 每一次打鼹鼠一定是从上一次打某只鼹鼠转移过来的,从打第 j 只鼹鼠能不能转移到打第 i 只鼹鼠,算一下曼哈顿距离和时间差就知道了. 那么就有一个 DP ,用 ...

  9. [BZOJ 3747] [POI 2015] Kinoman【线段树】

    Problem Link : BZOJ 3747 题解:ZYF-ZYF 神犇的题解 解题的大致思路是,当区间的右端点向右移动一格时,只有两个区间的左端点对应的答案发生了变化. 从 f[i] + 1 到 ...

随机推荐

  1. Luogu P3110 [USACO14DEC]驮运Piggy Back

    解题思路 看到下面很多人都在说什么遇到了之后要不要背着走,其实根本不需要,同样的我也是跑了三遍$SPFA$,求出了以$1$为起点到个点的$dist$,和以$2$为起点到个点的$dist$,还有以$n$ ...

  2. 题解 NOI2018 归程

    题解 NOI2018 归程 题意 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l, ...

  3. UVA - 10603 Fill(BFS求最小值问题)

    题目: 给出三个杯子(没有刻度线)的容量,起初之后第三个杯子是满的,其他的两个杯子是空的,容量分别是a.b.c.问最少需要倒多少升水才能让某一个杯子中的水有d升?如果不能恰好做到d升,就让某一个杯子里 ...

  4. numpy.random模块常用函数解析

    numpy.random模块中常用函数解析 numpy.random模块官方文档 1. numpy.random.rand(d0, d1, ..., dn)Create an array of the ...

  5. python3 判断大小写

    转自http://wangwei007.blog.51cto.com/68019/1134323 # 一.pyhton字符串的大小写转换, 常用的有以下几种方法: # 1.对字符串中所有字符(仅对字母 ...

  6. springcloud(八):熔断器Hystrix

    熔断器 雪崩效应 在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应.服务雪崩效应是一种因“服务提供者”的不可用导致“服务 ...

  7. BZOJ 3894 Luogu P4313 文理分科 (最小割)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3894 (luogu) https://www.luogu.org/pro ...

  8. Leetcode 133.克隆图

    克隆图 克隆一张无向图,图中的每个节点包含一个 label (标签)和一个 neighbors (邻接点)列表 . OJ的无向图序列化: 节点被唯一标记. 我们用 # 作为每个节点的分隔符,用 , 作 ...

  9. Uva122 Trees on the level

    Background Trees are fundamental in many branches of computer science. Current state-of-the art para ...

  10. Win32编程API 基础篇 -- 4.消息循环

    消息循环 理解消息循环 为了编写任何即使是最简单的程序,了解windows程序的消息循环和整个消息发送结构是非常有必要的.既然我们已经尝试了一点消息处理的东西,我们应该对整个程序有更深入的理解,如果你 ...