题目: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. vue基础---实例

    (1)数据和方法 ①响应式双向绑定 当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性.当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为 ...

  2. PHP 加密:Password Hashing API

    PHP 5.5 之后引入 Password hashing API 用于创建和校验哈希密码,它属于内核自带,无需进行任何扩展安装和配置.它主要提供了四个函数以供使用: password_hash(): ...

  3. 关押罪犯 - 并查集&优先队列

    题目地址:http://www.51cpc.com/web/problem.php?id=4261 Summarize: 此题最巧妙的是“敌人的敌人就是朋友!”,故需先将敌对关系放入优先队列,按怨恨值 ...

  4. C语言二叉树的创建、(先中后序)遍历以及存在的问题

    #include<stdlib.h> #include<stdio.h> #define True 1 #define False 0 typedef char TElemTy ...

  5. Java 中 break和 continue 的使用方法及区别

    break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后结束switch,不执行下面的语句. eg: publi ...

  6. ubuntu14.04 fcitx安装

    先卸载ibus sudo apt-get remove ibus (也可尝试不卸载ibus,直接安装fcitx) 添加源 sudo add-apt-repository ppa:fcitx-team/ ...

  7. Jmeter使用基础笔记-认识Jmeter

    我在工作过程中接触Jmeter不算特别多,对Jmeter的使用也只是限于基础阶段,不过对付基本的一些需求我想足够使用了.有好几个朋友问我关于Jmeter的问题,在此我将我在工作过程中的使用心得和总结的 ...

  8. [bzoj1867][Noi1999][钉子和小球] (动态规划)

    Description Input 第1行为整数n(2<=n<=50)和m(0<=m<=n).以下n行依次为木板上从上至下n行钉子的信息,每行中‘*’表示钉子还在,‘.’表示钉 ...

  9. Vue2.0 Props双向绑定报错简易处理办法

    在写项目的时候遇到了一个报错问题,虽然功能是正常运行,chrome的提示是:[Vue warn]: Avoid mutating a prop directly since the value wil ...

  10. Leetcode 133.克隆图

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