BZOJ4356Ceoi2014 Wall——堆优化dijkstra+最短路树
题目描述
输入
输出
样例输入
3 3
1 0 0
1 0 0
0 0 1
1 4 9 4
1 6 6 6
1 2 2 9
1 1 1
4 4 4
2 4 2
6 6 6
input 2
3 3
1 0 1
0 0 0
0 1 0
2 1 1 3
5 6 1 1
2 1 1 3
2 1 1
3 4 1
4 1 1
5 1 2
样例输出
38
output 2
22
提示

首先我们求出首都(即左上角)到每个城市左上角那个点的最短路形成的最短路树,那么有一个结论:所选的环一定将最短路树上的边圈在里面。
因为如果有一些最短路的边在环外,那么将环被这段最短路包含的部分换成这段最短路答案一定不会变劣。
所以我们现在就是要求在环不穿过城市和最短路树上的边的情况下最小。
我们将原图的每个点拆成四个点,如图所示。

即将每个点拆成左上、左下、右上、右下四个点。
对于每个原图点拆成的四个点中每对相邻点,只要他们两个之间的边不是城市边或最短路树上的边,那么就将他们两个连一条边权为$0$的边。
特别注意的是原图左上角那个点拆成的$1$号点不与$2,3$号点连边(原因下面会提到)。
对于原图每条边两侧的两对点(例如$A2,B1$和$A4,B3$)分别将他们连边,边权为原图这条边的边权。
这样我们跑出从左上角$3$号点到$2$号点的最短路即为答案。
因为连边时不穿过城市边和最短路树上的边,且起点保证在这些边的外围,所以能将所有城市都圈在环内。
而从$3$号点跑最短路到$2$号点保证它是一个环且最短。不允许穿过最短路树边相当于将每个城市与起点连通。
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define pr pair<ll,int>
#define PR pair<int,int>
using namespace std;
int vis[410][410];
int num;
int sum;
int n,m;
int head[650000];
ll d[650000];
int to[5200000];
int next[5200000];
int val[5200000];
int v[650000];
int w[410][410][5];
int tot;
int x,y;
int mp[400000];
inline void add(int x,int y,int z)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
inline int get(int x,int y)
{
x++,y++;
return (x-1)*(m+1)+y;
}
inline void back(int num,int &x,int &y)
{
x=(num-1)/(m+1)+1;
y=num-(m+1)*(x-1);
x--,y--;
}
namespace build
{
int head[170000];
ll d[170000];
int from[170000];
int vis[170000];
int to[680000];
int next[680000];
int val[680000];
int tot;
inline void add(int x,int y,int z)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
inline void dijkstra()
{
priority_queue< pr,vector<pr>,greater<pr> >q;
for(int i=1;i<=num;i++)
{
d[i]=1ll<<60;
}
d[1]=0;
q.push(make_pair(d[1],1));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])
{
continue;
}
vis[x]=1;
for(int i=head[x];i;i=next[i])
{
if(d[to[i]]>d[x]+1ll*val[i])
{
d[to[i]]=d[x]+1ll*val[i];
from[to[i]]=x;
q.push(make_pair(d[to[i]],to[i]));
}
}
}
}
}
inline void dijkstra()
{
priority_queue< pr,vector<pr>,greater<pr> >q;
for(int i=1;i<=num*4;i++)
{
d[i]=1ll<<60;
}
d[num+1]=0;
q.push(make_pair(d[num+1],num+1));
while(!q.empty())
{
int now=q.top().second;
q.pop();
if(v[now])
{
continue;
}
v[now]=1;
for(int i=head[now];i;i=next[i])
{
if(d[to[i]]>d[now]+1ll*val[i])
{
d[to[i]]=d[now]+1ll*val[i];
q.push(make_pair(d[to[i]],to[i]));
}
}
}
printf("%lld",d[num*2+1]);
}
inline int find(int x,int y)
{
if(x>y)
{
swap(x,y);
}
int a,b,c,d;
back(x,a,b);
back(y,c,d);
if(b==d)
{
return (c-1)*(m+1)+d+1;
}
else
{
return sum+c*m+d;
}
}
int main()
{
scanf("%d%d",&n,&m);
num=(n+1)*(m+1);
sum=n*(m+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&vis[i][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
scanf("%d",&x);
build::add(get(i-1,j),get(i,j),x);
build::add(get(i,j),get(i-1,j),x);
w[i-1][j][3]=w[i][j][1]=x;
}
}
for(int i=0;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
build::add(get(i,j-1),get(i,j),x);
build::add(get(i,j),get(i,j-1),x);
w[i][j-1][2]=w[i][j][4]=x;
}
}
build::dijkstra();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!vis[i-1][j-1]&&!vis[i-1][j]&&!vis[i][j-1]&&vis[i][j])
{
for(x=get(i-1,j-1);x!=1;x=build::from[x])
{
mp[find(build::from[x],x)]=1;
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(vis[i][j])
{
mp[find(get(i,j),get(i-1,j))]=1;
mp[find(get(i,j),get(i,j-1))]=1;
mp[find(get(i-1,j-1),get(i,j-1))]=1;
mp[find(get(i-1,j-1),get(i-1,j))]=1;
}
}
}
for(int i=1;i<=num;i++)
{
back(i,x,y);
if((!y||!mp[find(get(x,y),get(x,y-1))])&&i!=1)
{
add(i,2*num+i,0);
add(2*num+i,i,0);
}
if((!x||!mp[find(get(x,y),get(x-1,y))])&&i!=1)
{
add(i,num+i,0);
add(num+i,i,0);
}
if(x==n||!mp[find(get(x,y),get(x+1,y))])
{
add(num*2+i,num*3+i,0);
add(num*3+i,num*2+i,0);
}
if(y==m||!mp[find(get(x,y),get(x,y+1))])
{
add(num+i,num*3+i,0);
add(num*3+i,num+i,0);
}
if(y)
{
add(i,num+get(x,y-1),w[x][y][4]);
add(num*2+i,num*3+get(x,y-1),w[x][y][4]);
}
if(x)
{
add(i,num*2+get(x-1,y),w[x][y][1]);
add(num+i,num*3+get(x-1,y),w[x][y][1]);
}
if(x!=n)
{
add(num*2+i,get(x+1,y),w[x][y][3]);
add(num*3+i,num+get(x+1,y),w[x][y][3]);
}
if(y!=m)
{
add(num+i,get(x,y+1),w[x][y][2]);
add(num*3+i,num*2+get(x,y+1),w[x][y][2]);
}
}
dijkstra();
}
BZOJ4356Ceoi2014 Wall——堆优化dijkstra+最短路树的更多相关文章
- [CF1051F]The Shortest Statement_堆优化dij_最短路树_倍增lca
The Shortest Statement 题目链接:https://codeforces.com/contest/1051/problem/F 数据范围:略. 题解: 关于这个题,有一个重要的性质 ...
- 【bzoj1922】[Sdoi2010]大陆争霸 堆优化Dijkstra
题目描述 一张n个点m条边的图,通过每条边需要一定的时间.有一些限制条件,每个限制条件形如“x保护y”,表示到达y的最短时间不能小于到达x的最短时间(即如果在其之前到达,则需要等待至xd到达).问1到 ...
- 【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra
题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个 ...
- 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治
题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
- 洛谷 P3371 【模板】单源最短路径(堆优化dijkstra)
题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...
- PAT-1030 Travel Plan (30 分) 最短路最小边权 堆优化dijkstra+DFS
PAT 1030 最短路最小边权 堆优化dijkstra+DFS 1030 Travel Plan (30 分) A traveler's map gives the distances betwee ...
- 堆优化 dijkstra 简介
dijkstra 前言 原本我真的不会什么 dijkstra 只用那已死的 spfa ,还有各种玄学优化,可是,我不能相信一个已死的算法,就像我不能相信自己. ps : 虽然他已经活了 序 我站在镜子 ...
- BZOJ 3040 最短路 (堆优化dijkstra)
这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...
- UVA - 11374 - Airport Express(堆优化Dijkstra)
Problem UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...
随机推荐
- console 命令进行 JS 调试的灵活用法
1.console.log() 占位符 console.log 支持的占位符包括:字符(%s).整数(%d或%i).浮点数(%f)和对象(%o): console.log('字符串: %s, 整数: ...
- Oracle 一个用户将表权限赋给另一个用户
原文地址:https://blog.csdn.net/u012129031/article/details/76218764 1.将用户user1的表权限赋给用户user2 select 'gra ...
- 小菜鸡儿的第三次OO博客
规格化设计历史 规格化设计的历史目前网上的资料并不多,百度谷歌必应也表示无能为力...... 在这里结合现实情况讲一讲自己对程序规格化的理解,首先代码规格化对代码的影响是间接的,或许它不能让你代码里面 ...
- 2017百度软研(C++)
问了很多,不过很多也都没有问到,感觉有点偏,很深入的东西,越问越虚.第一次实习面试从百度开始,也从百度结束吧.看得见的差距,不想将就,所以还是拿最后一次机会去尝试.win or go home, 所以 ...
- Python-sys模块-61
sys 模块:和Python解释器打交道的模块 sys模块是与python解释器交互的一个接口 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退 ...
- H5 61-浮动元素贴靠现象
61-浮动元素贴靠现象 <!DOCTYPE html><html lang="en"><head> <meta charset=" ...
- 批量采集世纪佳缘会员图片及winhttp异步采集效率
原始出处:http://www.cnblogs.com/Charltsing/p/winhttpasyn.html 最近老有人问能不能绕过世纪佳缘的会员验证来采集图片,我测试了一下,发现是可以的. 同 ...
- PT与PX区别
字体大小的设置单位,常用的有2种:px.pt.这两个有什么区别呢? 先搞清基本概念:px就是表示pixel,像素,是屏幕上显示数据的最基本的点: pt就是point,是印刷行业常用单位,等于1/72英 ...
- DevOps工程师到底做些什么?
我们之前已经听到很多谈论DevOps和DevOps世界的最新趋势的事情,但是就DevOps工程师本身,到底干些什么呢? 在最纯粹的存在形式上来说,DevOps工程师是为了加快开发和运营团队之间的交付效 ...
- 项目管理、软件、禅道 VS JIRA
项目管理软件之争,禅道和JIRA大对比 - 简书https://www.jianshu.com/p/2533c0b7e456 [原创]项目管理软件之争,禅道和JIRA大对比 - zhengqiaoyi ...