题目大意:

有一个r*c的矩阵,上面有n个点有宝藏

每个有宝藏的点上都有传送门

传送门有三种:第一种可以传到该行任意一个有宝藏的点,第二种可以传到该列任意一个有宝藏的点,第三种可以传到周围的八连块上有宝藏的点

现在你可以在任意一个有宝藏的点开始,求你最多可以经过多少个不同的藏宝点

每个藏宝点可以多次进入,每个传送门可以多次使用

思路:

很容易可以看出这个矩阵并没有什么卵用

而此题的关键在于如何建图,建图所用数组见注释

建完之后,可以使用tarjan算法之一的求强连通分量

因为对于每个强连通分量,只要到达任意一个点,就可以到达其余所有点

然后我们缩点,把每个强连通分量都缩为一个点

再重新建图

这样图就会变成DAG,然后求一下最长链并统计每一个强连通分量内有几个点就好了

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define inf 2147483611
#define ll long long
#define MAXN 101001
using namespace std;
inline int read()
{
int x=,f=;
char ch;ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int dx[]={,,,-,-,-,,},dy[]={,,-,,,-,,-};//八连块用数组
map <int,int> m[*MAXN];//记录每个位置是否有藏宝点,因为数组开不下只能用map
vector <int> vr[*MAXN],vc[*MAXN];//记录每行每列所有藏宝点,用vector方便记录
int n,r,c;
int x[MAXN],y[MAXN];//记录每个点的横纵坐标
short t[MAXN];//记录每个点的传送门种类
int to[*MAXN],next[*MAXN],first[MAXN],cnt;//第一次图用邻接表
int to0[*MAXN],next0[*MAXN],first0[MAXN];//DAG第二次图用邻接表
int low[MAXN],dfn[MAXN],stp,scc,now,st[MAXN],top;//tarjan用数组
//scc记录一共有多少强连通分量,stp记录步数,st、top记录栈
int num[MAXN],blg[MAXN];//num记录每个强连通分量中有多少个点,blg记录每个点属于那个强连通分量
int deep[MAXN];//求最长链用,记录每个强连通分量能延伸的最长长度
int ans;
bool vis[MAXN];//第一次为tarjan用,第二次求最长链用
void add(int u,int v)//第一次建图
{
if(u==v) return ;
to[++cnt]=v,next[cnt]=first[u],first[u]=cnt;
}
void ADD(int u,int v) {to0[++cnt]=v,next0[cnt]=first0[u],first0[u]=cnt;}//第二次建图
void build()//第一次建图
{
int tmp,s;
for(int i=;i<=r;i++)//同一行的藏宝图
{
tmp=,s=vr[i].size();
for(int j=;j<s;j++) if(t[vr[i][j]]==) {tmp=vr[i][j];break;}
for(int j=;j<s;j++)
{
add(tmp,vr[i][j]);
if(t[vr[i][j]]==) add(vr[i][j],tmp);//不用连所有边,只需要这样就可以满足要求
}
}
for(int i=;i<=c;i++)//同一列,方法同上
{
tmp=,s=vc[i].size();
for(int j=;j<s;j++) if(t[vc[i][j]]==) {tmp=vc[i][j];break;}
for(int j=;j<s;j++)
{
add(tmp,vc[i][j]);
if(t[vc[i][j]]==) add(vc[i][j],tmp);
}
}
for(int i=;i<=n;i++)//八连块
if(t[i]==)
for(int j=;j<;j++) if(m[x[i]+dx[j]][y[i]+dy[j]]) add(i,m[x[i]+dx[j]][y[i]+dy[j]]);
}
void tarjan(int x)//tarjan求强连通分量
{
low[x]=dfn[x]=++stp;
st[++top]=x;vis[x]=;
for(int i=first[x];i;i=next[i])
if(!dfn[to[i]])
{tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}//在栈外且未被访问过
else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);//在栈内
if(low[x]==dfn[x])
{
scc++;now=;
while(now!=x)
{
now=st[top--];vis[now]=;
blg[now]=scc;num[scc]++;
}
}
}
void BUILD()//第二次建图
{
for(int i=;i<=n;i++)
for(int j=first[i];j;j=next[j])
if(blg[i]!=blg[to[j]]) ADD(blg[i],blg[to[j]]);
}
void dp(int x)//求最长链
{
vis[x]=;
for(int i=first0[x];i;i=next0[i])
{
if(!vis[to0[i]]) dp(to0[i]);
deep[x]=max(deep[x],deep[to0[i]]);//延伸
}
deep[x]+=num[x];
ans=max(ans,deep[x]);
}
int main()
{
n=read(),r=read(),c=read();
for(int i=;i<=n;i++)
{
x[i]=read(),y[i]=read(),t[i]=read();
m[x[i]][y[i]]=i;
vr[x[i]].push_back(i);
vc[y[i]].push_back(i);
}
build();
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
cnt=;
BUILD();
for(int i=;i<=scc;i++)
if(!vis[i]) dp(i);
printf("%d",ans);
}

bzoj 1924 所驼门王的宝藏的更多相关文章

  1. BZOJ 1924 所驼门王的宝藏(强连通分量缩点+DAG最长链)

    思路不是很难,因为宝藏只会在给出的n个点内有,于是只需要在这n个点里面连边,一个点如果能到达另一个点则连一条有向边, 这样用强连通分量缩点后答案就是DAG的最长链. 问题在于暴力建图是O(n^2)的, ...

  2. [BZOJ 1924][Sdoi2010]所驼门王的宝藏

    1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1285  Solved: 574[Submit][Sta ...

  3. 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

    1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Stat ...

  4. 「BZOJ1924」「SDOI2010」 所驼门王的宝藏 tarjan + dp(DAG 最长路)

    「BZOJ1924」[SDOI2010] 所驼门王的宝藏 tarjan + dp(DAG 最长路) -------------------------------------------------- ...

  5. 8.18 NOIP模拟测试25(B) 字符串+乌鸦喝水+所驼门王的宝藏

    T1 字符串 卡特兰数 设1为向(1,1)走,0为向(1,-1)走,限制就是不能超过$y=0$这条线,题意转化为从(0,0)出发,走到(n+m,n-m)且不越过$y=0$,然后就裸的卡特兰数,$ans ...

  6. 【题解】SDOI2010所驼门王的宝藏(强连通分量+优化建图)

    [题解]SDOI2010所驼门王的宝藏(强连通分量+优化建图) 最开始我想写线段树优化建图的说,数据结构学傻了233 虽然矩阵很大,但是没什么用,真正有用的是那些关键点 考虑关键点的类型: 横走型 竖 ...

  7. noip模拟5[string·matrix·big·所驼门王的宝藏]

    怎么说呢这一场考得还算可以呢 拿了120pts,主要是最后一个题灵光开窍,想起来是tarjan,然后勉勉强强拿了40pts,本来是可以拿满分的,害 没事考完了就要反思 这场考试我心态超好,从第一个题开 ...

  8. BZOJ 1924: [Sdoi2010]所驼门王的宝藏 【tarjan】

    Description 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先 知”的Alpaca L. Sotomon 是这个家族的领袖,外人也称其为“所驼门王”.所 驼门王毕生致力于维 ...

  9. [SDOI2010]所驼门王的宝藏

    题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...

随机推荐

  1. MySQL-----增

    增 **创建用户** create user 'alex'@'192.168.1.1' identified by '123123'; create user 'alex'@'192.168.1.%' ...

  2. Vue如何引入icon图标

             1.下载icon图标,推荐icomoon网站,里面有大量的矢量图标,也可以自定义,当然你也可以去阿里巴巴矢量图标库下载你所需要的小图标.点击进入icomoon网站点击右上角“IcoM ...

  3. Python xml文件处理

    什么是XML文件? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 从结构上,很像HTML超文本标记语言.但他们被设计的目的是不同的,具体如 ...

  4. python pip 安装一些包找不到的问题 Could not find a version that satisfies....

    有时我们使用下载python 自带的pip 安装一些工具包时,会报如下错误 找不到满意的版本,这时就是我们的pip可能需要升级了,所以使用 python -m pip install --upgrad ...

  5. HDU1241&POJ2386 dfs简单题

    2道题目都差不多,就是问和相邻所有点都有相同数据相连的作为一个联通快,问有多少个连通块 因为最近对搜索题目很是畏惧,总是需要看别人代码才能上手,就先拿这两道简单的dfs题目来练练手,顺便理一理dfs的 ...

  6. 新装mvn建第一个项目报错org.apache.maven.plugins:maven-resources-plugin:2.6

    1.第一次创建mvn项目会报maven-resources-plugin-2.6.jar错,原因是mvn无法自动下载这个jar包,多次删除这个目录下的C:\Users\Administrator\.m ...

  7. Organize Your Train part II 字典树(此题专卡STL)

    Organize Your Train part II Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8787   Acce ...

  8. UVA 11400_ Lighting System Design

    题意: 给定一系列灯泡的额定功率,电源价钱,一个灯泡的价格以及系统所需该种灯泡的数量.已知流过灯泡的电流相等,所以为省钱可以将电压小的灯泡换成电压大的灯泡,但是不能换成电压更小的灯泡,问最少要花多少钱 ...

  9. [bzoj1207][HNOI2004]打鼹鼠_动态规划

    打鼹鼠 bzoj-1207 HNOI-2004 题目大意:题目链接. 注释:略. 想法: $dp_i$表示打到了第$i$个鼹鼠时最多打了多少个鼹鼠. $O(n)$转移即可. 总时间复杂度$O(n^2) ...

  10. Spring boot精要

    1.自动配置:针对很多Spring应用程序的常见应用功能,SpringBoot能自动提供相关配置: 2.起步依赖:告诉SpringBoot需要什么功能,他就能引入需要的库: 3.命令行界面:这是Spr ...