Description

Input

第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti。Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意一列的“横天门”,2表示可以传送到任意一行第 yi列的“纵寰门”,3表示可以传送到周围 8格宫室的“自 由门”。 保证 1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。

Output

只有一个正整数,表示你确定的路线所经过不同藏宝宫室的最大数目。

Sample Input

10 7 7
2 2 1
2 4 2
1 7 2
2 7 3
4 2 2
4 4 1
6 7 3
7 7 1
7 5 2
5 2 1

Sample Output

9

HINT

测试点编号 N R C 1 16 20 20 2 300 1,000 1,000 3 500 100,000 100,000 4 2,500 5,000 5,000 5 50,000 5,000 5,000 6 50,000 1,000,000 1,000,000 7 80,000 1,000,000 1,000,000 8 100,000 1,000,000 1,000,000 9 100,000 1,000,000 1,000,000 10 100,000 1,000,000 1,000,000

/*
按照题目要求建图,缩点跑最长路。
*/
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#define N 100010
#define M 1000010
using namespace std;
int x[N],y[N],t[N],K,n,m;
int head1[N],head2[N],cnt;
int low[N],dfn[N],sta[N],ins[N],bl[N],num[N],indexx,top,scc;
int dep[N],vis[N],ans;
int dx[]={,,,,,-,-,-};
int dy[]={,-,,,-,,,-};
struct node{int v,pre;}e1[M],e2[M];
vector<int> a[M],b[M];
map<int,int> mp[M];
void add1(int u,int v){
if(u==v) return;
e1[++cnt].v=v;e1[cnt].pre=head1[u];head1[u]=cnt;
}
void add2(int u,int v){
e2[++cnt].v=v;e2[cnt].pre=head2[u];head2[u]=cnt;
}
void build(){
for(int i=;i<=n;i++){
int x=;
for(int j=;j<a[i].size();j++)
if(t[a[i][j]]==) {x=a[i][j];break;}
for(int j=;j<a[i].size();j++){
add1(x,a[i][j]);
if(t[a[i][j]]==) add1(a[i][j],x);
}
}
for(int i=;i<=m;i++){
int x=;
for(int j=;j<b[i].size();j++)
if(t[b[i][j]]==) {x=b[i][j];break;}
for(int j=;j<b[i].size();j++){
add1(x,b[i][j]);
if(t[b[i][j]]==) add1(b[i][j],x);
}
}
for(int i=;i<=K;i++)
if(t[i]==)
for(int j=;j<;j++){
int t=mp[x[i]+dx[j]][y[i]+dy[j]];
if(t) add1(i,t);
}
}
void tarjan(int u){
dfn[u]=low[u]=++indexx;
sta[++top]=u;ins[u]=;
for(int i=head1[u];i;i=e1[i].pre)
if(!dfn[e1[i].v]){
tarjan(e1[i].v);
low[u]=min(low[u],low[e1[i].v]);
}
else if(ins[e1[i].v])
low[u]=min(low[u],dfn[e1[i].v]);
int x;
if(low[u]==dfn[u]){
++scc;
do {
x=sta[top--];
ins[x]=;
bl[x]=scc;
num[scc]++;
}while(u!=x);
}
}
void rebuild(){
cnt=;
for(int i=;i<=K;i++)
for(int j=head1[i];j;j=e1[j].pre)
if(bl[i]!=bl[e1[j].v])
add2(bl[i],bl[e1[j].v]);
}
void dfs(int x){
vis[x]=;
for(int i=head2[x];i;i=e2[i].pre){
if(!vis[e2[i].v]) dfs(e2[i].v);
dep[x]=max(dep[x],dep[e2[i].v]);
}
dep[x]+=num[x];
ans=max(ans,dep[x]);
}
int main(){
scanf("%d%d%d",&K,&n,&m);
for(int i=;i<=K;i++){
scanf("%d%d%d",&x[i],&y[i],&t[i]);
mp[x[i]][y[i]]=i;
a[x[i]].push_back(i);
b[y[i]].push_back(i);
}
build();
for(int i=;i<=K;i++)
if(!dfn[i]) tarjan(i);
rebuild();
for(int i=;i<=scc;i++)
if(!vis[i]) dfs(i);
printf("%d",ans);
return ;
}

最新文章

  1. 我的Android最佳实践之—— Android更新UI的两种方法:handler与runOnUiThread()
  2. 在阿里云linux下使用SVN访问VisualSVN出错:SSL handshake failed: SSL error: Key usage violation in certificate has been detected
  3. insert into ... on duplicate key update 与 replace 区别
  4. 数据库MySQL调优实战经验总结
  5. Linux下软件的卸载
  6. Java Web开发 - 持久型/存储型XSS漏洞
  7. netty开发教程(一)
  8. 界面渐变特效 -- CSS实现 -- 兼容IE8
  9. 使用SQL命令批量替换WordPress站点中图片的URL链接地址
  10. 序列比对和构建进化树(clustalw和phylip)
  11. Java学习--泛型
  12. react组件在项目中的应用(基础知识)
  13. C# 实现子窗体控制父窗体的方法
  14. 为什么zookeeper会导致磁盘IO高【转】
  15. LVS小型系统架构搭建笔记
  16. C/S,B/S的区别与联系
  17. mysql主从复制搭建中几种log和pos详解
  18. PC初始化
  19. 05 Oracle process
  20. 如何使用phpmyadmin建立外键约束

热门文章

  1. c++question 004 c++基本数据类型有哪些?
  2. windows 安装nodejs及配置服务
  3. Finders Keepers-freecodecamp算法题目
  4. PAT 乙级 1017
  5. java的模运算
  6. 五、Linux 远程登录
  7. 解决国内网络Python2.X 3.X PIP安装模块连接超时问题
  8. linux正则表达式企业级深度实践案例2
  9. Ubuntu设置代理上网
  10. 数据存储之json文件处理和csv文件处理