1924: [Sdoi2010]所驼门王的宝藏

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit:
787  Solved: 318
[Submit][Status][Discuss]

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

Source

Solution

题目并不难.

很显然Tarjan缩点,重构图,然后在DAG上做DP,或者跑最长路

麻烦的在于建图....

需要用vector存在同一行上的格点,同一列上的格点,用map记录点的八连通,然后连边

连边的方式有技巧,选一个横/竖格,对同行同列的所有点连单向边,对横/竖格连双向;八连通的直接连就好

如果暴力连边,可能会出现一组WA的情况,可能需要再进行一遍拓扑排序

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 100010
int dx[]={,,,,,-,-,-},dy[]={,-,,,-,,,-};
struct EdgeNode{int next,to;}edge[maxn*],road[maxn*];
int cnt,tot,head[maxn],last[maxn];
void addedge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void insertedge(int u,int v) {if (u==v) return; addedge(u,v);}
void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
void insertroad(int u,int v) {addroad(u,v);}
int x[maxn],y[maxn],t[maxn],dfn[maxn],low[maxn],stack[maxn],num[maxn],belong[maxn],dp[maxn];
bool visit[maxn];
int n,r,c,ans,top,qcnt;
vector<int>h[maxn*],l[maxn*];
map<int,int>mp[maxn*];
void BuildGraph()
{
for (int i=; i<=r; i++)
{
int hn=h[i].size(),now=;
for (int j=; j<=hn-; j++) if (t[h[i][j]]==) {now=h[i][j]; break;}
for (int j=; j<=hn-; j++) {insertedge(now,h[i][j]); if (t[h[i][j]]==) insertedge(h[i][j],now);}
}
for (int i=; i<=c; i++)
{
int ln=l[i].size(),now=;
for (int j=; j<=ln-; j++) if (t[l[i][j]]==) {now=l[i][j]; break;}
for (int j=; j<=ln-; j++) {insertedge(now,l[i][j]); if (t[l[i][j]]==) insertedge(l[i][j],now);}
}
for (int i=; i<=n; i++)
if (t[i]==)
for (int xx,yy,j=; j<=; j++)
{
xx=x[i]+dx[j],yy=y[i]+dy[j];
if (mp[xx][yy]) insertedge(i,mp[xx][yy]);
}
}
void Tarjan(int x)
{
dfn[x]=low[x]=++tot; visit[x]=; stack[++top]=x;
for (int i=head[x]; i; i=edge[i].next)
{
if (!dfn[edge[i].to])
{
Tarjan(edge[i].to);
if (low[edge[i].to]<low[x]) low[x]=low[edge[i].to];
}
else
if(visit[edge[i].to] && dfn[edge[i].to]<low[x])
low[x]=dfn[edge[i].to];
}
if (dfn[x]==low[x])
{
int uu=; qcnt++;
while (x!=uu)
uu=stack[top--],num[qcnt]++,visit[uu]=,belong[uu]=qcnt;
}
}
void reBuildGraph()
{
for (int i=; i<=n; i++)
for (int j=head[i]; j; j=edge[j].next)
if (belong[i]!=belong[edge[j].to])
insertroad(belong[i],belong[edge[j].to]);
}
void DP(int now)
{
visit[now]=;
for (int i=last[now]; i; i=road[i].next)
{
if (!visit[road[i].to]) DP(road[i].to);
dp[now]=max(dp[now],dp[road[i].to]);
}
dp[now]+=num[now];
ans=max(ans,dp[now]);
}
int main()
{
n=read(); r=read(); c=read();
for (int i=; i<=n; i++)
{
x[i]=read(),y[i]=read(),t[i]=read();
mp[x[i]][y[i]]=i; h[x[i]].push_back(i); l[y[i]].push_back(i);
}
BuildGraph();
for (int i=; i<=n; i++) if (!dfn[i]) Tarjan(i);
reBuildGraph();
for (int i=; i<=qcnt; i++) if (!visit[i]) DP(i);
printf("%d\n",ans);
return ;
}

shabi题卡时卡内存是什么意思??

【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP的更多相关文章

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

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

  2. bzoj 1924 所驼门王的宝藏

    题目大意: 有一个r*c的矩阵,上面有n个点有宝藏 每个有宝藏的点上都有传送门 传送门有三种:第一种可以传到该行任意一个有宝藏的点,第二种可以传到该列任意一个有宝藏的点,第三种可以传到周围的八连块上有 ...

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

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

  4. 「模拟8.18」字符串(卡特兰数)·乌鸦喝水(树状数组,二分)·所驼门王的宝藏(tarjan,拓扑)

    最近好颓啊,所以啥都做不出来 简单说一下这次考试,分机房了,还分不同考卷,果然我还是留在二机房的蒟蒻, 大概也只有这样的简单题,才能勉强水个rank 3吧........ 其实不必管在哪个机房,努力便 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【MVC版本】MVC3、MVC4之MODEL验证大比拼

    1.密码验证 MVC3 [System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage = &quo ...

  2. font和lineheight冲突。

    font:14px bold arial; line-height:40px; 这样写font的话line-height不会有效,只要把font拆分写就有效,chrome ie ff下都是.

  3. 获取iframe加载完毕事件

    function IframeLoad(o,fn) { if (document.all) { o.attachEvent('onload', fn); } else { o.onload = fn; ...

  4. kindeditor编辑器里面 filterMode为false时候,允许输入任何代码

    kindeditor编辑器里面 filterMode为false时候,允许输入任何代码

  5. opencv 中对一个像素的rgb值或像素值进行操作的几个常用小办法【转】

    You can access the Image pixels in many ways:1. One using the Inbuilt macro2. One using the pointer ...

  6. CentOS7 下安装JDK1.7 和 Tomcat7

    一.下载JDK 和 Tomcat安装包 1.JDK1.7 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downl ...

  7. c++游戏服务器编程学习笔记(一)TCP/IP

    1. c++游戏服务器编程c++运行效率非常高2. TCP传输控制协议IP网际协议Socket 3.Linux 乌班图开源第三方库BOOST 4.80%游戏服务器端用C++工作量最大的地方是具体的游戏 ...

  8. sublime 函数跳转插件 — ctags 安装和使用

    ctags 是 sublime 下一个函数跳转的插件,可以让你方便地从函数调用的位置跳到函数定义的位置.相对于其他插件,ctags 的安装稍微有点复杂,这里记录下备忘. 首先,假设已经安装 Packa ...

  9. java并发:阻塞队列

    第一节 阻塞队列 1.1 初识阻塞队列 队列以一种先进先出的方式管理数据,阻塞队列(BlockingQueue)是一个支持两个附加操作的队列,这两个附加的操作是:在队列为空时,获取元素的线程会等待队列 ...

  10. (六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 本章我们讨论一个除前面的单例 ...