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

Solution

先考虑最朴素的方法,对于一个宝藏,从它向所有它能到达的点连有向边。于是得到了一个有向有环图,对这个图进行缩点,于是得到一个DAG,我们想要的答案就可以在这个DAG上dp求得

但是这样的边数是 \(O(n^2)\) 的,承受不了。于是考虑对于每一行和每一列建一个超级点,这个超级点可以到达当前列的所有宝藏点。而对于一个宝藏,如果它是第一种门,则将它向它所在的行的超级点连边,第二种门同理,第三种门就直接连能到达的宝藏。这样就把边数降了下来,可以承受

需要注意的是,这种缩完点后还要dp的问题,重新建边的时候要注意重边的问题

  1. #include<bits/stdc++.h>
  2. #define ui unsigned int
  3. #define ll long long
  4. #define db double
  5. #define ld long double
  6. #define ull unsigned long long
  7. const int MAXN=2100000+10,MAXM=1000000+10,MAXD=100000+10;
  8. int n,r,c,e,snt,cnt,Be[MAXN],DFN[MAXN],LOW[MAXN],f[MAXN],in[MAXN],beg[MAXN],ans,to[MAXM<<1],nex[MAXM<<1],Visit_Num,Stack[MAXN],Stack_Num,In_Stack[MAXN],val[MAXN],dr[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
  9. struct node{
  10. int x,y,t;
  11. };
  12. node type[MAXD];
  13. struct edge{
  14. int u,v;
  15. inline bool operator < (const edge &A) const {
  16. return u<A.u||(u==A.u&&v<A.v);
  17. };
  18. inline bool operator == (const edge &A) const {
  19. return u==A.u&&v==A.v;
  20. };
  21. };
  22. edge side[MAXM];
  23. std::queue<int> q;
  24. std::map<int,int> M;
  25. template<typename T> inline void read(T &x)
  26. {
  27. T data=0,w=1;
  28. char ch=0;
  29. while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
  30. if(ch=='-')w=-1,ch=getchar();
  31. while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
  32. x=data*w;
  33. }
  34. template<typename T> inline void write(T x,char ch='\0')
  35. {
  36. if(x<0)putchar('-'),x=-x;
  37. if(x>9)write(x/10);
  38. putchar(x%10+'0');
  39. if(ch!='\0')putchar(ch);
  40. }
  41. template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
  42. template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
  43. template<typename T> inline T min(T x,T y){return x<y?x:y;}
  44. template<typename T> inline T max(T x,T y){return x>y?x:y;}
  45. inline int id(int x,int y)
  46. {
  47. return (x-1)*c+y;
  48. }
  49. inline void insert(int x,int y,int opt=1)
  50. {
  51. if(opt)side[++snt]=(edge){x,y};
  52. to[++e]=y;
  53. nex[e]=beg[x];
  54. beg[x]=e;
  55. }
  56. inline void Tarjan(int x)
  57. {
  58. DFN[x]=LOW[x]=++Visit_Num;
  59. In_Stack[x]=1;
  60. Stack[++Stack_Num]=x;
  61. for(register int i=beg[x];i;i=nex[i])
  62. if(!DFN[to[i]])Tarjan(to[i]),chkmin(LOW[x],LOW[to[i]]);
  63. else if(In_Stack[to[i]]&&DFN[to[i]]<LOW[x])LOW[x]=DFN[to[i]];
  64. if(LOW[x]==DFN[x])
  65. {
  66. int temp;++cnt;
  67. do{
  68. temp=Stack[Stack_Num--];
  69. In_Stack[temp]=0;
  70. Be[temp]=cnt;
  71. val[cnt]+=(temp<=n?1:0);
  72. }while(temp!=x);
  73. }
  74. }
  75. inline void toposort()
  76. {
  77. for(register int i=1;i<=cnt;++i)
  78. if(!in[i])q.push(i),f[i]=val[i];
  79. while(!q.empty())
  80. {
  81. int x=q.front();
  82. q.pop();
  83. for(register int i=beg[x];i;i=nex[i])
  84. {
  85. chkmax(f[to[i]],f[x]+val[to[i]]);
  86. in[to[i]]--;
  87. if(!in[to[i]])q.push(to[i]);
  88. }
  89. }
  90. }
  91. int main()
  92. {
  93. read(n);read(r);read(c);
  94. for(register int i=1;i<=n;++i)
  95. {
  96. int x,y,t;read(x);read(y);read(t);
  97. insert(x+n,i);insert(y+r+n,i);
  98. M[id(x,y)]=i;
  99. type[i]=(node){x,y,t};
  100. }
  101. for(register int i=1;i<=n;++i)
  102. {
  103. int x=type[i].x,y=type[i].y,t=type[i].t;
  104. if(t==1)insert(i,x+n);
  105. if(t==2)insert(i,y+r+n);
  106. if(t==3)
  107. for(register int k=0;k<8;++k)
  108. {
  109. int dx=x+dr[k][0],dy=y+dr[k][1];
  110. if(M[id(dx,dy)])insert(i,M[id(dx,dy)]);
  111. }
  112. }
  113. for(register int i=1;i<=n+r+c;++i)
  114. if(!DFN[i])Tarjan(i);
  115. e=0;memset(beg,0,sizeof(beg));
  116. for(register int i=1;i<=snt;++i)side[i].u=Be[side[i].u],side[i].v=Be[side[i].v];
  117. std::sort(side+1,side+snt+1);
  118. snt=std::unique(side+1,side+snt+1)-side-1;
  119. for(register int i=1;i<=snt;++i)
  120. if(side[i].u!=side[i].v)insert(side[i].u,side[i].v,0),in[side[i].v]++;
  121. toposort();
  122. for(register int i=1;i<=cnt;++i)chkmax(ans,f[i]);
  123. write(ans,'\n');
  124. return 0;
  125. }

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

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

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

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

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

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

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

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

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

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

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

  6. [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. 安装Jenkins服务

    1.下载Jenkins 下载地址:https://jenkins.io/download/ 选择rpm包 2.启动服务 [root@node1 ~]# rpm -ivh jenkins-2.138.3 ...

  2. Python面向对象之异常捕获(一)-----抛出一个异常

    大部分的异常都继承自Exception这个类(而这个类有继承自BaseException这个类) 常见的异常 ValueError TypeError IndexError 抛出一个异常 下面这个类的 ...

  3. excel实用技巧——vlookup函数

    1.VLOOKUP函数的套路 VLOOKUP(要找谁,在哪儿找,返回第几列的内容,精确找还是近似找) 最后一个参数: 如果为0或FASLE,用精确匹配方式,而且支持无序查找: 如果为TRUE或被省略, ...

  4. Maltego——互联网情报聚合工具初探(转)

    有时候你可曾想过,从一个Email,或者Twitter,或是网站,甚至姓名等等,能找到一个人千丝万缕的联系,并把这些联系整合,利用起来?Maltego就是这样一款优秀而强大的工具.Maltego允许从 ...

  5. JavaEE笔记(十一)

    Spring beans使用参数占位符(JDBC配置读取示例) beans.xml配置文件 <?xml version="1.0" encoding="UTF-8& ...

  6. scala学习——(1)scala基础(上)

    scala> val x = 1 x: Int = 1 一.值与变量 值(val):赋值后不可变 val值名称:类型 = XXX 变量(var):赋值后可以改变  var变量名称:类型 = XX ...

  7. maven常用命令集

    maven常用命令 mvn compile  编译主程序源代码,不会编译test目录的源代码.第一次运行时,会下载相关的依赖包,可能会比较费时间. mvn test-compile  编译测试代码,c ...

  8. 一道面试题来了解线程notifyAll()和wait()的方法

    题目:三个线程,分别打印A.B.C,要求按ABC的顺序循环打印10次. package com.slowcity.crud.controller; public class PrintOneTwoTh ...

  9. LeetCode Letter Combinations of a Phone Number (DFS)

    题意 Given a digit string, return all possible letter combinations that the number could represent. A ...

  10. spring boot 实现文件下载

    html 代码 js部分 window.location.href= this.Baseurl+'/plan/down?file='+filename; spring boot 后台代码@GetMap ...