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

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+10;
 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=1;i<=v;i++){
 59         if(dfn[i]==0)
 60             Tarjan(i);
 61     }
 62     SweepEdge();
 63     for(int i=1;i<=v;i++){
 64         if(dp[i]==0)
 65             DFS(i);
 66     }
 67     printf("%d
",ans);
 68     return 0;
 69 }
 70 
 71 void Initialize(){
 72     scanf("%d%d%d",&v,&r,&c);
 73     for(int i=1;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]!=0)
 83         return;
 84     else{
 85         dp[root]=size[root];
 86         int max=0;
 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,0,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]==0){
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=1;k<=v;k++){
135         if(N[k].type==1){
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==2){
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==3){
150             for(int dx=-1;dx<=1;dx++){
151                 for(int dy=-1;dy<=1;dy++){
152                     if(dx!=0||dy!=0){
153                         int tmp=m[N[k].x+dx][N[k].y+dy];
154                         if(tmp!=0&&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
",from,to);
166     top->from=from;
167     top->to=to;
168     top->next=head[from];
169     head[from]=top++;
170 }
Backup

 

原文地址:https://www.cnblogs.com/rvalue/p/7658378.html