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<=100000, R<=100000, C<=100000

Solution

一开始的正解的想法让我以为边数太多然后叉掉了……其实是可以过的……

很容易可以想到做法就是门和门之间连边,然后tarjan缩个点再拓扑排序跑个最长路就完事了。不过直接连边$n^2$肯定会GG。

对于同一行的门来说,横门间显然可以相互传送,只需要选定一个横门,然后向这一行的其他横门连双向边,向这一行的其他门连单向边,这样就可以保证缩点后横门在一个强连通分量里了。列同理。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#define N (100009)
using namespace std; struct Node{int x,y,t,id;}a[N];
struct Edge{int to,next;}edge[N*];
int n,m,r,c,e1[N*],e2[N*],Ind[N],dp[N];
int head[N],num_edge;
int Dfn[N],Low[N],stack[N],ID[N],Num[N];
int top,id_num,dfs_num;
int dx[]={,,,,,,-,-,-},dy[]={,,-,,,-,,,-};
vector<int>Line[N*],List[N*];
map<int,int>Map[N*];
queue<int>q;
bool vis[N]; void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
if (!m) e1[num_edge]=u,e2[num_edge]=v;
} void Tarjan(int x)
{
Dfn[x]=Low[x]=++dfs_num;
stack[++top]=x; vis[x]=true;
for (int i=head[x]; i; i=edge[i].next)
if (!Dfn[edge[i].to])
Tarjan(edge[i].to),Low[x]=min(Low[x],Low[edge[i].to]);
else if (vis[edge[i].to])
Low[x]=min(Low[x],Dfn[edge[i].to]);
if (Low[x]==Dfn[x])
{
vis[x]=false; ID[x]=++id_num; Num[id_num]++;
while (stack[top]!=x)
{
vis[stack[top]]=false;
Num[id_num]++;
ID[stack[top--]]=id_num;
}
top--;
}
} void Add()
{
for (int i=; i<=r; ++i)
{
int x=,sz=Line[i].size();
for (int j=; j<sz; ++j)
if (a[Line[i][j]].t==){x=Line[i][j]; break;}
if (!x) continue;
for (int j=; j<sz; ++j)
if (Line[i][j]!=x)
{
add(x,Line[i][j]);
if (a[Line[i][j]].t==) add(Line[i][j],x);
}
}
for (int i=; i<=c; ++i)
{
int x=,sz=List[i].size();
for (int j=; j<sz; ++j)
if (a[List[i][j]].t==){x=List[i][j]; break;}
if (!x) continue;
for (int j=; j<sz; ++j)
if (List[i][j]!=x)
{
add(x,List[i][j]);
if (a[List[i][j]].t==) add(List[i][j],x);
}
}
for (int i=; i<=n; ++i)
if (a[i].t==)
{
int x=a[i].x,y=a[i].y;
for (int j=; j<=; ++j)
{
int t=Map[x+dx[j]][y+dy[j]];
if (t) add(i,t);
}
}
} void Toposort()
{
int ans=;
for (int i=; i<=id_num; ++i) ans=max(ans,Num[i]);
for (int i=; i<=id_num; ++i) if (!Ind[i]) q.push(i),dp[i]=Num[i];
while (!q.empty())
{
int x=q.front(); q.pop();
for (int i=head[x]; i; i=edge[i].next)
{
int y=edge[i].to; Ind[y]--;
if(!Ind[y]) q.push(y);
dp[y]=max(dp[y],dp[x]+Num[y]);
ans=max(ans,dp[y]);
}
}
printf("%d\n",ans);
} int main()
{
scanf("%d%d%d",&n,&r,&c);
for (int i=; i<=n; ++i)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].t);
Line[a[i].x].push_back(i);
List[a[i].y].push_back(i);
Map[a[i].x][a[i].y]=i;
}
Add();
for (int i=; i<=n; ++i)
if (!Dfn[i]) Tarjan(i); memset(head,,sizeof(head));
m=num_edge; num_edge=;
for (int i=; i<=m; ++i)
if (ID[e1[i]]!=ID[e2[i]])
add(ID[e1[i]],ID[e2[i]]),Ind[ID[e2[i]]]++;
Toposort();
}

BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)的更多相关文章

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

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

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

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

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

    题目 输入格式 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室,类型为 Ti.Ti ...

  4. bzoj1924: [Sdoi2010]所驼门王的宝藏

    陈年老题又来水一发啊啊啊 构图狗了一点,然后其实强连通缩点dij找最长路就没了. 没调出来有点气,直接打了第9个点的表.... 来逛blog的你教教我呗 #include<cstdio> ...

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

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

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

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

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

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

  8. [LuoguP2403][SDOI2010]所驼门王的宝藏

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

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

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

随机推荐

  1. Java并发编程之volatile关键字解析

    一内存模型的相关概念 二并发编程中的三个概念 三Java内存模型 四深入剖析volatile关键字 五使用volatile关键字的场景 volatile这个关键字可能很多朋友都听说过,或许也都用过.在 ...

  2. [转]weui-wxss WeUI for 小程序 为微信小程序量身设计

    本文转自:https://github.com/weui/weui-wxss/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=tou ...

  3. JQuery extend()与工具方法、实例方法

    使用jQuery的时候会发现,jQuery中有的函数是这样使用的: $.get(); $.post(); $.getJSON(); 有些函数是这样使用的: $('div').css(); $('ul' ...

  4. SSIS教程:创建简单的ETL包

    SSIS: Microsoft SQL Server Integration Services.是一个可用于生成高性能数据集成解决方案的平台,其中包括数据仓库的提取(Extract).转换(Trans ...

  5. Expression Blend实例中文教程(1) - 开篇

    随着计算机软件开发分工细节化,微软对已有的产品线进行了调整,在保持原有经典开发工具Visual Studio基础上,又推出了一套新的设计开发工具系列,Expression Studio. Expres ...

  6. 使用sqlcmd进行MS-dos方式查询

    在windows选择‘运行’vista需要以管理员身份运行,打开命令提示符窗口 要连接到sql server服务器,必须指定服务器名称,安装命名实例中的,还必须指定实例名.默认情况下,sqlcmd使用 ...

  7. 将JavaScript语句插入HTML文档

    (1) 使用 <SCRIPT> 标签将语句嵌入文档 <script type="text/javascript"> function Que() { } & ...

  8. (原创).Net将EF运用于Oralce一 准备工作

    网上有很多EF运用于Oracle的博文,但是找了半天发现大多数博文大都语焉不详,于是决定自己折腾. 首先我的开发工具为vs2010,那么最适用于VS2010的EF版本为多少呢?答案是EF5.我在Sta ...

  9. Markdown调查

    Markdown调查 一.Editor.md   文档详细,使用者较多 1.1 主要特性 支持“标准”Markdown / CommonMark和Github风格的语法,也可变身为代码编辑器: 支持实 ...

  10. css的字体样式怎么写

    为保证字体的正常加载 sans-serif不能丢 font-family:'MicrosoftYahei','微软雅黑',Arial,'宋体',sans-serif;