洛谷 P2403 [SDOI2010]所驼门王的宝藏 题解
题目描述




分析
先放一张图便于理解

这一道题如果暴力建图会被卡成\(n^{2}\)
实际上,在我们暴力建图的时候,有很多边都是重复的
假如一行当中有许多横天门的话,我们就不必要把这一行当中的所有点和每一个横天门都连上一条边
因为横天门之间是相互联通的,无论我们走到哪一个横天门,都可以走到同一行的另一个横天门
因此,我们可以先把这些横天门连成一个环,在这些横天门中选取一个点作为代表,连向同一行中不是横天门的点
对于纵寰门也是如此
剩下的任意门直接暴力扫一遍建边即可
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
int head[maxn],tot=1;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int dx[10]={0,0,1,-1,1,1,-1,-1};
int dy[10]={1,-1,0,0,-1,1,-1,1};
struct asd{
int to,next;
}b[maxn];
void ad(int aa,int bb){
b[tot].to=bb;
b[tot].next=head[aa];
head[aa]=tot++;
}
struct jll{
int jlx,jly,jlb,id;
}jl[maxn];
int n,r,c,nx,ny,nb,rd[maxn];
int dfn[maxn],low[maxn],dfnc,sta[maxn],top,js,shuyu[maxn],siz[maxn];
void tar(int xx){
dfn[xx]=low[xx]=++dfnc;
sta[++top]=xx;
for(int i=head[xx];i!=-1;i=b[i].next){
int u=b[i].to;
if(!dfn[u]){
tar(u);
low[xx]=min(low[u],low[xx]);
} else if(!shuyu[u]){
low[xx]=min(low[xx],dfn[u]);
}
}
if(dfn[xx]==low[xx]){
js++;
while(1){
int now=sta[top--];
shuyu[now]=js;
siz[js]++;
if(now==xx) break;
}
}
}
map<pair<int,int>,bool> mp;
struct asd2{
int to,next,val;
}b2[maxn];
int h2[maxn],t2=1;
void ad2(int aa,int bb,int cc){
b2[t2].to=bb;
b2[t2].next=h2[aa];
b2[t2].val=cc;
h2[aa]=t2++;
}
int f[maxn],ans=0;
void tp(){
queue<int> q;
q.push(0);
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=h2[now];i!=-1;i=b2[i].next){
int u=b2[i].to;
rd[u]--;
f[u]=max(f[u],f[now]+b2[i].val);
if(rd[u]==0) q.push(u);
}
}
}
bool cmplh(jll aa,jll bb){
if(aa.jlb==bb.jlb && aa.jlx==bb.jlx) return aa.jly<bb.jly;
if(aa.jlb==bb.jlb) return aa.jlx<bb.jlx;
return aa.jlb<bb.jlb;
}
bool cmpll(jll aa,jll bb){
if(aa.jlb==bb.jlb && aa.jly==bb.jly) return aa.jlx<bb.jlx;
if(aa.jlb==bb.jlb) return aa.jly<bb.jly;
if(aa.jlb==2) return 1;
return 0;
}
bool cmpry(jll aa,jll bb){
return aa.jlb>bb.jlb;
}
map<pair<int,int>,int> mpp;
int htm[maxn],ztm[maxn];
int main(){
memset(head,-1,sizeof(head));
memset(h2,-1,sizeof(h2));
n=read(),r=read(),c=read();
for(int i=1;i<=n;i++){
jl[i].jlx=read();
jl[i].jly=read();
jl[i].jlb=read();
jl[i].id=i;
mpp[make_pair(jl[i].jlx,jl[i].jly)]=jl[i].id;
}
sort(jl+1,jl+1+n,cmplh);
for(int i=1;i<=n;i++){
if(jl[i].jlb!=1) break;
int ks=jl[i].id;
while(jl[i].jlx==jl[i+1].jlx && jl[i+1].jlb==1){
ad(jl[i].id,jl[i+1].id);
i++;
}
ad(jl[i].id,ks);
htm[jl[i].jlx]=jl[i].id;
}
sort(jl+1,jl+1+n,cmpll);
for(int i=1;i<=n;i++){
if(jl[i].jlb!=2) break;
int ks=jl[i].id;
while(jl[i].jly==jl[i+1].jly && jl[i+1].jlb==2){
ad(jl[i].id,jl[i+1].id);
i++;
}
ad(jl[i].id,ks);
ztm[jl[i].jly]=jl[i].id;
}
sort(jl+1,jl+1+n,cmpry);
for(int i=1;i<=n;i++){
if(jl[i].jlb!=3) break;
int nx=jl[i].jlx,ny=jl[i].jly;
for(int j=0;j<8;j++){
int mx=nx+dx[j];
int my=ny+dy[j];
if(mpp[make_pair(mx,my)]){
ad(jl[i].id,mpp[make_pair(mx,my)]);
}
}
}
for(int i=1;i<=n;i++){
if(jl[i].jlb==1) continue;
int ks=jl[i].id;
if(htm[jl[i].jlx]!=0) ad(htm[jl[i].jlx],jl[i].id);
}
for(int i=1;i<=n;i++){
if(jl[i].jlb==2) continue;
int ks=jl[i].id;
if(ztm[jl[i].jly]!=0) ad(ztm[jl[i].jly],jl[i].id);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tar(i);
}
for(int i=1;i<=n;i++){
for(int j=head[i];j!=-1;j=b[j].next){
int u=b[j].to;
if(shuyu[i]!=shuyu[u] && mp[make_pair(shuyu[i],shuyu[u])]==0){
ad2(shuyu[i],shuyu[u],siz[shuyu[u]]);
rd[shuyu[u]]++;
mp[make_pair(shuyu[i],shuyu[u])]=1;
}
}
}
for(int i=1;i<=js;i++){
if(rd[i]==0){
ad2(0,i,siz[i]);
rd[i]++;
}
}
tp();
for(int i=1;i<=js;i++){
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}
洛谷 P2403 [SDOI2010]所驼门王的宝藏 题解的更多相关文章
- 洛谷 2403 [SDOI2010] 所驼门王的宝藏
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先知”的Alpaca L. Sotomon是这个家族的领袖,外人也称其为“所驼门王”.所驼门王毕生致力于维护家族的安定与和谐, ...
- 洛咕 P2403 [SDOI2010]所驼门王的宝藏
简单tarjan. 一行的横天门如果暴力连边会被卡成平方,所以只要相邻两个横天门连双向边,再随便选一个横天门向整行连边即可.纵寰门同理.ziyou门直接map暴力连边. 然后tarjan直接dp. / ...
- Luogu P2403 [SDOI2010]所驼门王的宝藏
比较显然的缩点+拓扑排序题,只不过要建虚点优化建边. 首先我们发现在一个SCC里的点都是可以一起对答案产生贡献的,因此先缩成DAG,然后拓扑找最长链. 但是我们发现这题最坏情况下边数会达到恐怖的\(O ...
- BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP
记住:map一定要这么用: if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy ...
- [bzoj1924]P2403 [SDOI2010]所驼门王的宝藏
tarjan+DAG 上的 dp 难点在于建图和连边,其实也不难,就是细节挺恶心 我和正解对拍拍出来 3 个错误... 传送门:luogu bzoj 题目描述 有座宫殿呈矩阵状,由 \(R\times ...
- [BZOJ 1924][Sdoi2010]所驼门王的宝藏
1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1285 Solved: 574[Submit][Sta ...
- 【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)
[题解]SDOI2010所驼门王的宝藏(强连通分量+优化建图) 最开始我想写线段树优化建图的说,数据结构学傻了233 虽然矩阵很大,但是没什么用,真正有用的是那些关键点 考虑关键点的类型: 横走型 竖 ...
- [SDOI2010]所驼门王的宝藏
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...
- [LuoguP2403][SDOI2010]所驼门王的宝藏
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...
随机推荐
- 区间dp 能量项链 洛谷p1063
题目大意:如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为 (Mars单位),新产生的珠子的头标记为m,尾标记为n. 需要时,Mars人就用吸盘夹住 ...
- Java常用的文档地址
https://docs.oracle.com/en/ https://docs.oracle.com/en/java/javase/13/ specifications--->langua ...
- springboot + rabbitmq 用了消息确认机制,感觉掉坑里了
本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...
- swaager-ui 美化版
简介 Swagger UI允许任何人(无论您是开发团队还是用户)都可以可视化API资源并与之交互,而无需任何实现逻辑.它是根据您的OpenAPI(以前称为Swagger)规范自动生成的,具有可视化文档 ...
- 利用CSS变量实现炫酷的悬浮效果
最近,我从 Grover网站 上发现以一个好玩儿的悬停动画,这个动画是将鼠标移动到订阅按钮上移动光标,会跟随光标实现相应的彩色渐变. 这个想法很简单,但是它能使这个按钮脱颖而出,人们一下子就注意到它了 ...
- css3-pointer-events_demo
该demo定义了一个菜单,点击了一次之后就不能再点击,另外其中也用到了flex布局,可直接将代码复制运行即可 <html> <head> <meta name=" ...
- Android屏幕适配技巧
屏幕适配一直是困扰 Android 开发工程师的一大问题,但是随着近几年各种屏幕适配方案的诞生,以及谷歌各种适配控件的推出,屏幕适配也显得越来越容易,这节课我们就来总结一下关于屏幕适配的那些技巧. C ...
- Linux多任务编程之二:fork()函数及其基础实验(转)
来源:CSDN 作者:王文松 转自Linux公社 fork()函数 在 Linux 中创建一个新进程的唯一方法是使用fork()函数.fork()函数是 Linux 系统中一个非常重要的函数,和咱们 ...
- Python爬虫:手把手教你写迷你爬虫架构
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:我爱学Python 语言&环境 语言:继续用Python开路 ...
- python PEP8开发规范
为了使得代码更美观,方便阅读,建议遵循下PEP8规范 每行长度最大不要超过79. 换行可以使用反斜杠,换行点要在操作符的后面敲回车. 类个top-level函数定义之间空两行:类中的方法定义之间空一行 ...