BZOJ1924 [Sdoi2010]所驼门王的宝藏 【建图 + tarjan】
题目

输入格式
第一行给出三个正整数 N, R, C。 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti。Ti是一个1~3间的整数, 1表示可以传送到第 xi行任意一列的“横天门”,2表示可以传送到任意一行第 yi列的“纵寰门”,3表示可以传送到周围 8格宫室的“ziyou门”。 保证 1≤xi≤R,1≤yi≤C,所有的传送门位置互不相同。
输出格式
只有一个正整数,表示你确定的路线所经过不同藏宝宫室的最大数目。
输入样例
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
输出样例
9
提示

题解
把图建出来后就是tarjan + dp了
建图比较烦
我们将其按x排序,先将横向边建上,当一排存在多个横向边时,它们之间两两连边,过于费空间,只连一个环就好了
竖向边也是一样的
最后是第三种边,排个序二分查找就好了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 1000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,N,M;
int x[maxn],y[maxn],id[maxn],t[maxn];
inline bool cmp1(const int& a,const int& b){
return x[a] == x[b] ? t[a] < t[b] : x[a] < x[b];
}
inline bool cmp2(const int& a,const int& b){
return y[a] == y[b] ? t[a] < t[b] : y[a] < y[b];
}
inline bool cmp3(const int& a,const int& b){
return x[a] == x[b] ? y[a] < y[b] : x[a] < x[b];
}
int h[maxn],ne = 2,h2[maxn],ne2 = 2;
struct EDGE{int to,nxt;}ed[maxm],e[maxm];
inline void build(int u,int v){
ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
//printf("build (%d) to (%d)\n",u,v);
}
inline void add(int u,int v){
e[ne2] = (EDGE){v,h2[u]}; h2[u] = ne2++;
}
inline bool check(const int& p,const int& X,const int& Y){
return x[id[p]] == X ? y[id[p]] >= Y : x[id[p]] > X;
}
int lowb(int X,int Y){
int l = 1,r = n,mid;
while (l < r){
mid = l + r >> 1;
if (check(mid,X,Y)) r = mid;
else l = mid + 1;
}
return l;
}
int st[maxn],top;
void Build(){
sort(id + 1,id + 1 + n,cmp1);
for (int i = 1; i <= n; i++){
int u = i; top = 0;
while (u <= n){
if (x[id[u]] != x[id[i]]) break;
if (t[id[u]] == 1) st[++top] = id[u];
u++;
}
if (!top) continue;
if (top > 1){
for (int j = 1; j < top; j++) build(st[j],st[j + 1]);
build(st[top],st[1]);
}
for (int j = i; j < u; j++) if (t[id[j]] != 1) build(st[1],id[j]);
i = --u;
}
sort(id + 1,id + 1 + n,cmp2);
for (int i = 1; i <= n; i++){
int u = i; top = 0;
while (u <= n){
if (y[id[u]] != y[id[i]]) break;
if (t[id[u]] == 2) st[++top] = id[u];
u++;
}
if (!top) continue;
if (top > 1){
for (int j = 1; j < top; j++) build(st[j],st[j + 1]);
build(st[top],st[1]);
}
for (int j = i; j < u; j++) if (t[id[j]] != 2) build(st[1],id[j]);
i = --u;
}
sort(id + 1,id + 1 + n,cmp3);
for (int i = 1; i <= n; i++){
if (t[id[i]] != 3) continue;
int u = lowb(x[id[i]] - 1,y[id[i]] - 1);
for (int j = u; j <= n && x[id[j]] + 1 == x[id[i]] && y[id[j]] >= y[id[i]] - 1 && y[id[j]] <= y[id[i]] + 1; j++)
build(id[i],id[j]);
u = lowb(x[id[i]],y[id[i]] - 1);
for (int j = u; j <= n && x[id[j]] == x[id[i]] && y[id[j]] >= y[id[i]] - 1 && y[id[j]] <= y[id[i]] + 1; j++)
if (id[i] != id[j]) build(id[i],id[j]);
u = lowb(x[id[i]] + 1,y[id[i]] - 1);
for (int j = u; j <= n && x[id[j]] - 1 == x[id[i]] && y[id[j]] >= y[id[i]] - 1 && y[id[j]] <= y[id[i]] + 1; j++)
build(id[i],id[j]);
}
}
int dfn[maxn],low[maxn],Scc[maxn],scci,cnt,val[maxn];
void dfs(int u){
dfn[u] = low[u] = ++cnt;
st[++top] = u;
Redge(u){
if (!dfn[to = ed[k].to]){
dfs(to);
low[u] = min(low[u],low[to]);
}else if (!Scc[to]) low[u] = min(low[u],dfn[to]);
}
if (dfn[u] == low[u]){
scci++;
do{
Scc[st[top]] = scci; val[scci]++;
}while(st[top--] != u);
}
}
void tarjan(){
for (int i = 1; i <= n; i++) if (!dfn[i]) dfs(i);
}
queue<int> q;
int inde[maxn],f[maxn];
void solve(){
for (int i = 1; i <= n; i++){
int u = Scc[i];
Redge(i) if (Scc[to = ed[k].to] != u)
add(u,Scc[to]),inde[Scc[to]]++;
}
for (int i = 1; i <= scci; i++) if (!inde[i]) q.push(i),f[i] = val[i];
int u,ans = 0;
while (!q.empty()){
u = q.front(); q.pop();
ans = max(ans,f[u]);
for (int k = h2[u],to; k; k = e[k].nxt){
f[to = e[k].to] = max(f[to],f[u] + val[to]);
if (!(--inde[to])) q.push(to);
}
}
for (int i = 1; i <= scci; i++)
ans = max(ans,f[i]);
printf("%d\n",ans);
}
void readin(){
n = read(); N = read(); M = read();
for (int i = 1; i <= n; i++)
x[i] = read(),y[i] = read(),t[i] = read(),id[i] = i;
}
int main(){
readin();
Build();
tarjan();
solve();
return 0;
}
BZOJ1924 [Sdoi2010]所驼门王的宝藏 【建图 + tarjan】的更多相关文章
- [SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]
题面传送门: 传送门 思路: 看完题建模,容易得出是求单向图最长路径的问题 那么把这张图缩强联通分量,再在DAG上面DP即可 然而 这道题的建图实际上才是真正的考点 如果对于每一个点都直接连边到它所有 ...
- BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)
Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...
- bzoj1924: [Sdoi2010]所驼门王的宝藏
陈年老题又来水一发啊啊啊 构图狗了一点,然后其实强连通缩点dij找最长路就没了. 没调出来有点气,直接打了第9个点的表.... 来逛blog的你教教我呗 #include<cstdio> ...
- 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP
1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 787 Solved: 318[Submit][Stat ...
- [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是这个家族的领袖,外人也称其为"所驼门王". ...
- BZOJ 1924: [Sdoi2010]所驼门王的宝藏 【tarjan】
Description 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为“先 知”的Alpaca L. Sotomon 是这个家族的领袖,外人也称其为“所驼门王”.所 驼门王毕生致力于维 ...
随机推荐
- PHP识别二维码功能,php-zbarcode 安装
php-zbarcode是PHP识别二维码的扩展. 下面是安装方法,安装前要先安装ImageMagick.zbar. php-zbarcode 下载地址 安装ImageMagick: yum inst ...
- 忘记Centos7.2下root用户密码后的处理方式
1)重启系统 重新启动系统后并按f2键,进入如下的界面,再按e键. 2)修改启动内核代码 在代码的linux16行中,将ro rhgb的ro修改为rw init=/sysroot/bin/sh. 3) ...
- Android学习总结(十一)———— Adapter的使用
一.Adapter的基本概念 UI控件都是跟Adapter(适配器)打交道的,了解并学会使用这个Adapter很重要, Adapter是用来帮助填充数据的中间桥梁,简单点说就是:将各种数据以合适的形式 ...
- github上不了改下host
207.97.227.239 github.com 65.74.177.129 www.github.com 207.97.227.252 nodeload.github.com 207.97.227 ...
- 编程中什么是「Context(上下文)」?
https://www.zhihu.com/question/26387327 每一段程序都有很多外部变量.只有像Add这种简单的函数才是没有外部变量的.一旦你的一段程序有了外部变量,这段程序就不完整 ...
- JAVA中IP和整数相互转化(含有掩码的计算)
import java.net.InetAddress;/** * 用于IP和整数之间的相互转换 * @author Andy.Wang * */public class IPv4Util { ...
- 一、新手必会Python基础
博客内容: 1.基础语法 2.运算符 3.流程控制 4.列表.元组.字典.集合 5.字符串 6.文件操作 一.基础语法 1.标识符 命名规则: 以字母.下划线开头 其他部分由字母.数字或下划线组成 不 ...
- Docker基础内容之网络基础
网络命名空间基本原理 单机版多容器实例网络交互原理 在宿主机上面打开两张网卡eth0与eth1,打通两张网卡的链路 在test1上面启动一个veth网卡,创建一个namespace:并桥接到eth0上 ...
- SpringBoot入门,新建SpringBoot项目
一.在Spring Initializr中创建初始化项目 https://start.spring.io/ 二.通过maven导入Idea中(解压后的项目) 解压文件 黄色的为项目需要的真正的代码 , ...
- 五. web开发基础
一.HTML 二.CSS 三.JavaScript 四.web框架 1.web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端 ...