题目: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. oracle查询没有主键的表

    select table_name from user_tables a where not exists (select * from user_constraints b where b.cons ...

  2. /etc/updatedb.conf配置文件

    [root@localhost ~]# vi /etc/updatedb.conf PRUNE_BIND_MOUNTS = "yes" PRUNEFS = "9p afs ...

  3. anaconda镜像

    下载一个包老是下载不下来,于是放弃了官方版改为国内镜像. 清华镜像 (打开Anaconda Prompt   或者 打开cmd,运行下面的命令) conda config --add channels ...

  4. [Luogu] P3225 [HNOI2012]矿场搭建

    题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...

  5. Centos6文本安装教程

    Centos6.4文本方式安装 虚拟机中文本安装(内存512),内存大于512默认为图形安装 1.选择安装媒体,在vbox中选skip跳过 2.选择安装语言(chinese(simplifired)简 ...

  6. python爬虫26 | 把数据爬取下来之后就存储到你的MySQL数据库。

    小帅b说过 在这几篇中会着重说说将爬取下来的数据进行存储 上次我们说了一种 csv 的存储方式 这次主要来说说怎么将爬取下来的数据保存到 MySQL 数据库 接下来就是 学习python的正确姿势 真 ...

  7. (四)Python3 循环语句——for

    for循环的一般格式如下: for <variable> in <sequence>: <statements> else: <statements> ...

  8. Wind rotor states

    test test Table of Contents 1. Wind rotor states 1.1. Turbulent Wake State 1.2. Vortex Ring State 1. ...

  9. calculate Cp history (from Fluent) using Matlab

    input data : unscaled time history of moment/thrust from ANSYS fluent example of input data, "m ...

  10. js获取昨天,最近7天,最近30天通用方法

    function formatDate (val) { // 格式化时间 let start = new Date(val) let y = start.getFullYear() let m = ( ...