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

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1285  Solved: 574
[Submit][Status][Discuss]

Description

Input

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

题解

按照题意建好有向边, 跑一遍 $Tarjan$ 缩成 $DAG$ 之后直接 $O(n)$  $DP$ 一遍求最大值即可.

至于快速建边, 可以用 $std::set$ 维护同一行/同一列的所有节点编号, 二维 $std::map$ 维护各个节点的位置. 不过如果所有点都在同一行的话可能会$GG$

参考代码

GitHub

  1. #include <set>
  2. #include <map>
  3. #include <stack>
  4. #include <vector>
  5. #include <cstdio>
  6. #include <cstring>
  7. #include <cstdlib>
  8. #include <iostream>
  9. #include <algorithm>
  10.  
  11. const int MAXV=1e5+;
  12. const int MAXE=5e6;
  13.  
  14. struct Edge{
  15. int from;
  16. int to;
  17. Edge* next;
  18. };
  19. Edge E[MAXE];
  20. Edge* head[MAXV];
  21. Edge* top=E;
  22.  
  23. struct Node{
  24. int x;
  25. int y;
  26. int type;
  27. };
  28. Node N[MAXV];
  29.  
  30. int v;
  31. int c;
  32. int r;
  33. int ans;
  34. int clk;
  35. int scc;
  36. int dp[MAXV];
  37. int dfn[MAXV];
  38. int low[MAXV];
  39. int size[MAXV];
  40. int belong[MAXV];
  41.  
  42. bool inStack[MAXV];
  43.  
  44. std::stack<int> s;
  45. std::map< int, std::set<int> > sx,sy;
  46. std::map< int, std::map<int,int> > m;
  47.  
  48. void Build();
  49. void DFS(int);
  50. void Tarjan(int);
  51. void SweepEdge();
  52. void Initialize();
  53. void Insert(int,int);
  54.  
  55. int main(){
  56. Initialize();
  57. Build();
  58. for(int i=;i<=v;i++){
  59. if(dfn[i]==)
  60. Tarjan(i);
  61. }
  62. SweepEdge();
  63. for(int i=;i<=v;i++){
  64. if(dp[i]==)
  65. DFS(i);
  66. }
  67. printf("%d\n",ans);
  68. return ;
  69. }
  70.  
  71. void Initialize(){
  72. scanf("%d%d%d",&v,&r,&c);
  73. for(int i=;i<=v;i++){
  74. scanf("%d%d%d",&N[i].x,&N[i].y,&N[i].type);
  75. sx[N[i].x].insert(i);
  76. sy[N[i].y].insert(i);
  77. (m[N[i].x])[N[i].y]=i;
  78. }
  79. }
  80.  
  81. void DFS(int root){
  82. if(dp[root]!=)
  83. return;
  84. else{
  85. dp[root]=size[root];
  86. int max=;
  87. for(Edge* i=head[root];i!=NULL;i=i->next){
  88. DFS(i->to);
  89. max=std::max(max,dp[i->to]);
  90. }
  91. dp[root]+=max;
  92. ans=std::max(dp[root],ans);
  93. }
  94. }
  95.  
  96. void SweepEdge(){
  97. // puts("SE");
  98. Edge* ed=top;
  99. top=E;
  100. memset(head,,sizeof(head));
  101. for(Edge* i=E;i!=ed;i++){
  102. if(belong[i->from]!=belong[i->to])
  103. Insert(belong[i->from],belong[i->to]);
  104. }
  105. }
  106.  
  107. void Tarjan(int root){
  108. dfn[root]=low[root]=++clk;
  109. inStack[root]=true;
  110. s.push(root);
  111. for(Edge* i=head[root];i!=NULL;i=i->next){
  112. if(dfn[i->to]==){
  113. Tarjan(i->to);
  114. low[root]=std::min(low[root],low[i->to]);
  115. }
  116. else if(inStack[i->to]){
  117. low[root]=std::min(low[root],dfn[i->to]);
  118. }
  119. }
  120. if(dfn[root]==low[root]){
  121. scc++;
  122. int top;
  123. do{
  124. top=s.top();
  125. inStack[top]=false;
  126. size[scc]++;
  127. belong[top]=scc;
  128. s.pop();
  129. }while(top!=root);
  130. }
  131. }
  132.  
  133. void Build(){
  134. for(int k=;k<=v;k++){
  135. if(N[k].type==){
  136. std::map< int, std::set<int> >::iterator px=sx.find(N[k].x);
  137. for(std::set<int>::iterator i=(*px).second.begin();i!=(*px).second.end();++i){
  138. if(k!=*i)
  139. Insert(k,*i);
  140. }
  141. }
  142. else if(N[k].type==){
  143. std::map< int, std::set<int> >::iterator py=sy.find(N[k].y);
  144. for(std::set<int>::iterator i=(*py).second.begin();i!=(*py).second.end();++i){
  145. if(k!=*i)
  146. Insert(k,*i);
  147. }
  148. }
  149. else if(N[k].type==){
  150. for(int dx=-;dx<=;dx++){
  151. for(int dy=-;dy<=;dy++){
  152. if(dx!=||dy!=){
  153. int tmp=m[N[k].x+dx][N[k].y+dy];
  154. if(tmp!=&&tmp!=k){
  155. Insert(k,tmp);
  156. }
  157. }
  158. }
  159. }
  160. }
  161. }
  162. }
  163.  
  164. inline void Insert(int from,int to){
  165. // printf("Insert %d to %d\n",from,to);
  166. top->from=from;
  167. top->to=to;
  168. top->next=head[from];
  169. head[from]=top++;
  170. }

Backup

[BZOJ 1924][Sdoi2010]所驼门王的宝藏的更多相关文章

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

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

  2. bzoj 1924 [Sdoi2010]所驼门王的宝藏(构图,SCC,DP)

    Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...

  3. 【刷题】BZOJ 1924 [Sdoi2010]所驼门王的宝藏

    Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...

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

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

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

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

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

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

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

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

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

    BZOJ 1924 内存要算准,我MLE了两次. 建立$n + r + c$个点,对于一个点$i$的坐标为$(x, y)$,连边$(n + x, i)$和$(n + r + y, i)$,代表这一列和 ...

  9. BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP

    记住:map一定要这么用: if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy ...

随机推荐

  1. Oracle 存储过程A

    create or replace procedure users_procedure is cursor users_cursor is select * from users; v_id user ...

  2. redis数据类型(六)Sorted set类型

    一.sorted set类型 sorted set是有序集合,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,会自动重新按新的值调整顺序.可以理解了有两列的 m ...

  3. vue之生命周期的一点总结

    vue的生命周期的过程提供了我们执行自定义逻辑的机会,好好理解它的生命周期,对我们很有帮助. 一.vue实例的生命周期(vue2.0) 二.生命周期描述:(参考截图) 三.例子 window.vm = ...

  4. 把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像

    在上一个part<把AspDotNetCoreMvc程序运行在Docker上-part1>,已经将成功将aspdotnetcore程序运行在两个不同的容器中,目前两个容器的内容完全相同,只 ...

  5. linux ssh 免密码登录的配置过程

    # ssh-keygen -t rsa -C "自定义描述" -f ~/.ssh/自定义生成的rsa文件 # cd ./.ssh # touch config # 粘贴  Host ...

  6. js常用字符处理方法

    JS自带函数concat将两个或多个字符的文本组合起来,返回一个新的字符串.var a = "hello";var b = ",world";var c = a ...

  7. jquery 获取 tagName(JQuery如何得到tagName?)

    在javascript中要取得tagName十分简单,但在jQuery中官方文档却没有记载,在一通百度和谷歌之后,尝试了不少所谓秘技,都不能正确得到,经过自己的验证,终于找到了方法,于是记录下来以备忘 ...

  8. 【9】log4net 实例

    一.创建项目并添加nuget: Install-Package log4net   二.添加配置文件 <configuration> <configSections> < ...

  9. java:模拟队列操作

    import java.util.LinkedList; public class Myqueue { private LinkedList<Object> linkedList; pub ...

  10. Spring入门(一)— IOC、DI

    一.Spring介绍 Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成 ...