[BZOJ 4144] Petrol
Link:
Solution:
一道不错的图论综合题
因为只询问关键点,因此重点是要求出关键点之间的最短路,以最短路建图
记$nst[i]$为离$i$最近的关键点:可以发现$A->B$的最短路径上,一定是前一半$nst[i]$为$A$,后一半$nst[i]$为$B$
否则设$nst[x]=C$,则$A->C->B$由于经过了$C$的加油一定不会更差
因此对于符合条件的$A->B$连边就建出了新图(如果离线的话仅修改权值不更改节点也可行)
接下来为了使连通的最大边最小跑$Kruskal$,此时分为两种方式:
Solution A:Offline
明显是更简单的解法,学会利用离线啊!
将$Query$按$b$从小到大排序
每次只连接$edge(u,v) (w(u,v)<=b)$,最后判断$x,y$是否在一个点集中即可
Solution B:Online
如果要强制在线也可以做,而且算常用套路
先跑$Kruskal$,将图转化为了树,每次询问在树上倍增查找
Code:
#include<bits/stdc++.h> using namespace std;
typedef pair<int,int> P;
const int MAXN=2e5+;
struct data{int x,y,w;}edge[MAXN];
struct E{int to,nxt,w;}e[MAXN<<];
priority_queue<P,vector<P>,greater<P> > pq;
int belong[MAXN],f[MAXN][],mx[MAXN][],dep[MAXN],nst[MAXN],cnt=;
int n,m,s,q,tot,head[MAXN],pos[MAXN],dist[MAXN],res[MAXN],vis[MAXN],fa[MAXN]; void add_edge(int from,int to,int cost)
{
e[++tot].nxt=head[from];e[tot].w=cost;e[tot].to=to;head[from]=tot;
e[++tot].nxt=head[to];e[tot].w=cost;e[tot].to=from;head[to]=tot;
} int find(int x){return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
bool cmp(data a,data b){return a.w<b.w;} void dijkstra()
{
for(int i=;i<=s;i++)
dist[pos[i]]=,nst[pos[i]]=pos[i],pq.push(P(,pos[i]));
while(!pq.empty())
{
int u=pq.top().second;pq.pop();
if(vis[u]) continue;vis[u]=true;
for(int i=head[u];i;i=e[i].nxt)
if(dist[e[i].to]>dist[u]+e[i].w)
{
dist[e[i].to]=dist[u]+e[i].w;nst[e[i].to]=nst[u];
pq.push(P(dist[e[i].to],e[i].to));
}
}
} void MST()
{
memset(head,,sizeof(head));
int e_cnt=;tot=;
for(int i=;i<=n;i++) fa[i]=i;
for(int i=;i<=m;i++)
{
int x=edge[i].x,y=edge[i].y;
if(nst[x]==nst[y]) continue;
edge[++e_cnt].w=dist[x]+dist[y]+edge[i].w;
edge[e_cnt].x=nst[x];edge[e_cnt].y=nst[y];
}
sort(edge+,edge+e_cnt+,cmp); for(int i=;i<=e_cnt;i++)
{
int fx=find(edge[i].x),fy=find(edge[i].y);
if(fx!=fy)
fa[fx]=fa[fy],add_edge(edge[i].x,edge[i].y,edge[i].w);
}
} void dfs(int x,int bloc)
{
belong[x]=bloc;
for(int i=;(<<i)<=dep[x];i++)
f[x][i]=f[f[x][i-]][i-],
mx[x][i]=max(mx[x][i-],mx[f[x][i-]][i-]);
for(int i=head[x];i;i=e[i].nxt)
{
if(e[i].to==f[x][]) continue;
dep[e[i].to]=dep[x]+;
f[e[i].to][]=x;mx[e[i].to][]=e[i].w;
dfs(e[i].to,bloc);
}
} int check(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y],ret=;
for(int i=;i<=;i++)
if(t&(<<i)) ret=max(ret,mx[x][i]),x=f[x][i]; for(int i=;i>=;i--)
if(f[x][i]!=f[y][i])
ret=max(ret,max(mx[x][i],mx[y][i])),
x=f[x][i],y=f[y][i]; if(x!=y) ret=max(ret,max(mx[x][],mx[y][]));
return ret;
} int main()
{
scanf("%d%d%d",&n,&s,&m);
for(int i=;i<=s;i++) scanf("%d",&pos[i]);
for(int i=;i<=m;i++)
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w),
add_edge(edge[i].x,edge[i].y,edge[i].w); memset(dist,0x3f,sizeof(dist));
dijkstra();MST(); for(int i=;i<=s;i++)
if(!belong[pos[i]]) dfs(pos[i],++cnt); scanf("%d",&q);
for(int i=;i<=q;i++)
{
int x,y,b;scanf("%d%d%d",&x,&y,&b);
if(belong[x]!=belong[y]) puts("NIE");
else puts((check(x,y)<=b)?"TAK":"NIE");
}
return ;
}
Online
#include<bits/stdc++.h> using namespace std;
typedef pair<int,int> P;
const int MAXN=2e5+;
struct data{int x,y,w;}edge[MAXN];
struct E{int to,nxt,w;}e[MAXN<<];
struct Query{int x,y,b,id;}q[MAXN];
priority_queue<P,vector<P>,greater<P> > pq;
int n,m,s,tot,head[MAXN],pos[MAXN],dist[MAXN],f[MAXN],res[MAXN],vis[MAXN]; void add_edge(int from,int to,int cost)
{
e[++tot].nxt=head[from];e[tot].w=cost;e[tot].to=to;head[from]=tot;
e[++tot].nxt=head[to];e[tot].w=cost;e[tot].to=from;head[to]=tot;
} int find(int x){return (f[x]==x)?x:(f[x]=find(f[x]));}
bool cmp1(data a,data b){return a.w<b.w;}
bool cmp2(Query a,Query b){return a.b<b.b;} void dijkstra()
{
for(int i=;i<=s;i++)
dist[pos[i]]=,pq.push(P(,pos[i]));
while(!pq.empty())
{
P t=pq.top();pq.pop();
int u=t.second;
if(t.first>dist[u]) continue; //这里的判断一定要加,或用vis也行
for(int i=head[u];i;i=e[i].nxt) //否则疯狂TLE
if(dist[e[i].to]>dist[u]+e[i].w)
dist[e[i].to]=dist[u]+e[i].w,pq.push(P(dist[e[i].to],e[i].to));
}
} int main()
{
scanf("%d%d%d",&n,&s,&m);
for(int i=;i<=s;i++) scanf("%d",&pos[i]);
for(int i=;i<=m;i++)
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w),
add_edge(edge[i].x,edge[i].y,edge[i].w); memset(dist,0x3f,sizeof(dist));dijkstra();
for(int i=;i<=m;i++)
edge[i].w+=dist[edge[i].x]+dist[edge[i].y]; scanf("%d",&s);
for(int i=;i<=s;i++)
scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].b),q[i].id=i;
sort(edge+,edge+m+,cmp1);
sort(q+,q+s+,cmp2); int cur=;
for(int i=;i<=n;i++) f[i]=i;
for(int i=;i<=s;i++)
{
while(cur<=m&&edge[cur].w<=q[i].b)
{
int fx=find(edge[cur].x),fy=find(edge[cur].y);
if(fx!=fy) f[fx]=fy;cur++;
}
res[q[i].id]=(find(q[i].x)==find(q[i].y));
}
for(int i=;i<=s;i++)
puts(res[i]?"TAK":"NIE");
return ;
}
Offline
Review:
1、关于$dijkstra$的模板:
一定要保证每个点只对其后继更新一次!不管是用$vis[i]$还是$top.first>dist[top.second]$
2、如果可以离线,查看能否通过将询问排序简化查询过程
3、套路:将图转为树,然后树上倍增查询
[BZOJ 4144] Petrol的更多相关文章
- BZOJ 4144: [AMPPZ2014]Petrol
4144: [AMPPZ2014]Petrol Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 457 Solved: 170[Submit][Sta ...
- BZOJ.4144.[AMPPZ2014]Petrol(Kruskal重构树)
BZOJ 看别人代码的时候发现哪一步都很眼熟,突然想起来,就在四个月前我好像看过还给别人讲过?mmp=v= 果然不写写就是容易忘.写了好歹忘了的时候还能复习呢(虽然和看别人的好像也没多少差别?). 首 ...
- BZOJ 4144 Dijkstra+Kruskal+倍增LCA
思路: 先把所有的加油站 push进按weight排序的优先队列里 对于每个不是加油站的点 找到到它的点的最短路以及它来源的加油站 如果x和y有边 且x和y加油站的来源不一样 则它可以连边 跑一边Kr ...
- 【BZOJ】【4144】【AMPPZ2014】Petrol
最短路+最小生成树+倍增 图论问题中综合性较强的一题= =(Orz vfk) 比较容易发现,关键的还是有加油站的这些点,其他点都是打酱油的. 也就是说我们重点是要求出 关键点之间的最短路. 这玩意…… ...
- 【BZOJ】4144: [AMPPZ2014]Petrol
题意 给定一个\(n\)个点.\(m\)条边的带权无向图,其中有\(s\)个点是加油站.每辆车都有一个油量上限\(b\),即每次行走距离不能超过\(b\),但在加油站可以补满.\(q\)次询问,每次给 ...
- 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)
4144: [AMPPZ2014]Petrol Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 752 Solved: 298[Submit][Sta ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
随机推荐
- 12.25模拟赛T2
https://www.luogu.org/blog/a23333/post-xing-xuan-mu-ni-sai-path-ji-wang-zui-duan-lu 如果设f[i]表示从i到n的期望 ...
- DES 加密解密
[概念] 数据加密算法(Data Encryption Algorithm,DEA)是一种对称加密算法,很可能是使用最广泛的密钥系统,特别是在保护金融数据的安全中,最初开发的DEA是嵌入硬件中的.通常 ...
- im4java学习---阅读documentation文档
Utilities----im提供的一些工具类 ①.读取图片文件信息---Info类 我们之前的做法: op.format("width:%w,height:%h,path:%d%f,siz ...
- 如何去掉Json字符串中反斜杠
做项目的时候,遇到了这样的问题,前台传来的Json字符串在实体类中不对应(无法转换为实体类),而且传来的数据项是跟着数据库中的表的变动而变动的(不能重写实体类). 前台Json字符串为: string ...
- 数据结构&图论:K短路-可持久化可并堆
本来A*就可以搞定的题,为了怕以后卡复杂度,找了个这么个方法 现阶段水平不够就不补充算法分析部分了 对于图G,建立一个以终点t为起点的最短路径构成的最短路径树 (就是反着跑一遍最短路,然后对于一个不为 ...
- 不谈OI:高二(13)最后一次班班有歌声
最后一次班班有歌声了…… 自己因为搞oi并没有参加,只是决赛的时候幕后放了放背景视频…… 不管怎么说,我们班唱的很棒啊,全部人都很棒! 说真的我为我们班骄傲 视频: https://v.qq.com/ ...
- 汕头市队赛 SRM16 T2
描述 猫和老鼠,看过吧?猫来了,老鼠要躲进洞里.在一条数轴上,一共有n个洞,位置分别在xi,能容纳vi只老鼠.一共有m只老鼠位置分别在Xi,要躲进洞里,问所有老鼠跑进洞里的距离总和最小是多少. 输入格 ...
- Linux 远程登录——(九)
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...
- pyhton发送邮件
# import smtplib # from email.mime.text import MIMEText # _user = "你的qq邮箱" # _pwd = " ...
- 美团网技术团队分享的MySQL索引及慢查询优化教程
MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程师的必修课,我们经常会从职位 ...