题目大意:给定一张无向图。每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路

显然我们须要从点1出发走到某个和点1相邻的点上,然后沿最短路走到还有一个和点1相邻的点上,然后回到点1

那么我们将与点1相邻的点都设为关键点。然后将点1从图中删除。题目转化成了给定图上的一些关键点求近期点对

枚举每一个点显然会T

考虑每次将关键点划分为两个集合A,B。然后将A中的每一个点x的初始距离设为len(1,x),跑最短路,然后用B中的每一个点y的disy+len(y,1)统计答案,再将AB反转做一次

这样仅仅要随意点对都被分别划分到两个集合中至少一次,那么答案就被更新完了

怎样划分呢?我们考虑依照二进制拆分,对于每一位划分一次,将该位上为0的划分到A集合中。该位上为1的划分到B集合中

因为两个数至少有一位不同,因此随意点对至少被划分了一次

这样划分O(log2n)次就够了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 5050
using namespace std;
struct abcd{
int to,f,next;
}table[M<<2];
int head[M],tot;
int n,m,top,ans=0x3f3f3f3f;
pair<int,pair<int,int> >stack[M<<1];
int f[M];
void Add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
namespace Heap{
int heap[M],pos[M],top;
void Push_Up(int t)
{
while(t>1)
{
if( f[heap[t]]<f[heap[t>>1]] )
swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t>>=1;
else
break;
}
}
void Insert(int x)
{
heap[++top]=x;
pos[x]=top;
Push_Up(top);
}
void Pop()
{
pos[heap[1]]=0;
heap[1]=heap[top--];
if(top) pos[heap[1]]=1;
int t=2;
while(t<=top)
{
if( f[heap[t+1]]<f[heap[t]] )
++t;
if( f[heap[t]]<f[heap[t>>1]] )
swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t<<=1;
else
break;
}
}
}
void Dijkstra()
{
using namespace Heap;
int i;
for(i=1;i<=n;i++)
Insert(i);
while(Heap::top)
{
int x=heap[1];Pop();
for(i=head[x];i;i=table[i].next)
if(f[table[i].to]>f[x]+table[i].f)
{
f[table[i].to]=f[x]+table[i].f;
Push_Up(pos[table[i].to]);
}
}
}
int main()
{
int i,j,x,y,z1,z2;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&z1,&z2);
if(x>y) swap(x,y),swap(z1,z2);
if(x==1)
stack[++top]=make_pair(y,make_pair(z1,z2));
else
Add(x,y,z1),Add(y,x,z2);
}
for(j=1;j<=n;j<<=1)
{
memset(f,0x3f,sizeof f);
for(i=1;i<=top;i++)
if(i&j)
f[stack[i].first]=stack[i].second.first;
Dijkstra();
for(i=1;i<=top;i++)
if(~i&j)
ans=min(ans,f[stack[i].first]+stack[i].second.second); memset(f,0x3f,sizeof f);
for(i=1;i<=top;i++)
if(~i&j)
f[stack[i].first]=stack[i].second.first;
Dijkstra();
for(i=1;i<=top;i++)
if(i&j)
ans=min(ans,f[stack[i].first]+stack[i].second.second);
}
cout<<ans<<endl;
return 0;
}

BZOJ 2069 POI2004 ZAW 堆优化Dijkstra的更多相关文章

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

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

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

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

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

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

  4. BZOJ 3040 最短路 (堆优化dijkstra)

    这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...

  5. 2069: [POI2004]ZAW

    2069: [POI2004]ZAW 链接 题意: 给定一张带权图(边是双向的,但不同方向长度不同).求从1出发,至少经过除1外的一个点,再回到1的最短路.点和边不能重复经过. n≤5000,m≤10 ...

  6. UVA - 11374 - Airport Express(堆优化Dijkstra)

    Problem    UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...

  7. BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra

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

  8. 配对堆优化Dijkstra算法小记

    关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...

  9. POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]

    题目链接:http://poj.org/problem?id=3635 题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]. 一些口胡: ...

随机推荐

  1. php的fastcgi_finish_request()函数

    php的fastcgi_finish_request()函数 功能: 此函数冲刷(flush)所有响应的数据给客户端并结束请求. 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行. 返回值: ...

  2. LeetCode OJ--Longest Consecutive Sequence ***

    http://oj.leetcode.com/problems/longest-consecutive-sequence/ 起初想的是排序,查了下O(n)的排序算法有计数排序.基数排序.桶排序.后来考 ...

  3. java中线程切换的开销

    思路: 开三个线程A,B,C 线程A不断的调用LockSupport.park()阻塞自己,一旦发现自己被唤醒,调用Thread.interrupted()清除interrupt标记位,同时增加自增计 ...

  4. javascript 函数初探 (五)--- 几种类型的函数

    即时函数: 目前我们已经讨论了匿名函数在回调时的应用.接下来,我们来看看匿名函数的另一种应用实例 --- javascript即时函数: 比如: ( function(){ alert('her'); ...

  5. Android开发者选项——Gpu呈现模式分析

    对于Android用户来说,无论你用的什么品牌的手机,在开发者选项中都能发现“玄学曲线”的开关,之所以称其为玄学曲线,还是因为它被很多网友用于测试一个说不清道不明的东西——流畅度.到底多流畅才叫流畅, ...

  6. Android 中状态栏、标题栏、View的大小及区分

    1.获得状态栏的高度(状态栏相对Window的位置): Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisp ...

  7. GOPATH设置

    go help gopath查看gopath的原文帮助信息 go env查看gopath的配置 GOPATH与工作空间 前面我们在安装Go的时候看到需要设置GOPATH变量,Go从1.1版本到1.7必 ...

  8. Don't Panic! KRACK 没你想象的那么糟

    上海交通大学密码与计算机安全实验室(LoCCS)软件安全小组(GoSSIP)版权所有,转载请与作者取得联系! 著名的计算机学术安全会议CCS在2017年录用了一篇名为Key Reinstallatio ...

  9. DICOM:DICOM Print 服务详细介绍

      目录(?)[-] 背景 DICOM Print服务数据流 DICOM Print服务各部分关系 DICOM Print服务具体实现   背景: 昨天专栏中发表了一篇关于DICOM Print的博文 ...

  10. redis主从连接不成功错误

    redis主从连接不成功错误 学习了:https://blog.csdn.net/wzqzhq/article/details/64919133 需要增加 masterauth  password.. ...