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

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

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1303  Solved: 582
[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

 

【题解】

这题空间卡的太紧了吧。。。

洛谷上死活交不过,就差大概10kb

实在卡不过去了,冒死交BZOJ,居然过了

把门之间建图即可,用map处理九宫格。

每行/列能够行走行/列的门只需选一个,与其他

同类别门连双向,不同类连单向

tarjan + DAG最长路模板

除了DP部分跟hwzer写的很像?

我那么蒟蒻不读上几遍dalao的代码怎么会写。。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <map>
  6 #include <vector> 
  7 #define min(a, b) ((a) < (b) ? (a) : (b))
  8 #define max(a, b) ((a) > (b) ? (a) : (b))
  9 
 10 inline void read(int &x)
 11 {
 12     x = 0;char ch = getchar(), c = ch;
 13     while(ch < '0' || ch > '9')c = ch, ch = getchar();
 14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
 15     if(c == '-')x = -x;
 16 }
 17 
 18 const int INF = 0x3f3f3f3f;
 19 const int MAXN = 100000 + 1;
 20 const int MAXR = 1000000 + 1;
 21 const int dx[8] = {0,0,1,1,1,-1,-1,-1};
 22 const int dy[8] = {1,-1,0,1,-1,0,1,-1};
 23 
 24 std::map<int, int> mp[MAXR];
 25 int r, c, n;
 26 std::vector<int> row[MAXR], line[MAXR];
 27 int x[MAXN], y[MAXN], pos[MAXN];
 28 
 29 struct Edge
 30 {
 31     int v,next;
 32     Edge(int _v, int _next){v = _v;next = _next;}
 33     Edge(){}
 34 }edge1[MAXR], edge2[MAXR];
 35 int head1[MAXN], head2[MAXN], cnt1, cnt2;
 36 inline void insert1(int a, int b)
 37 {
 38     edge1[++cnt1] = Edge(b, head1[a]);
 39     head1[a] = cnt1;
 40 }
 41 inline void insert2(int a, int b)
 42 {
 43     edge2[++cnt2] = Edge(b, head2[a]);
 44     head2[a] = cnt2;
 45 }
 46 
 47 int dfn[MAXN], t, top, group, size[MAXN];
 48 bool b[MAXN];
 49 
 50 void dfs(int u)
 51 {
 52     dfn[u] = y[u] = ++t;b[u] = 1;pos[++top] = u;
 53     for(register int pos = head1[u];pos;pos = edge1[pos].next)
 54     {
 55         if(!dfn[edge1[pos].v])
 56         {
 57             dfs(edge1[pos].v);
 58             y[u] = min(y[u], y[edge1[pos].v]);
 59         }
 60         else if(b[edge1[pos].v] && y[u] > dfn[edge1[pos].v])
 61             y[u] = dfn[edge1[pos].v];
 62     }
 63     if(y[u] == dfn[u])
 64     {
 65         ++ group;
 66         int now = -1;
 67         while(now != u)
 68         {
 69             now = pos[top];-- top;
 70             x[now] = group;
 71             b[now] = 0;
 72             ++ size[group];
 73         }
 74     }
 75 }
 76 
 77 void tarjan()
 78 {
 79     for(register int i = 1;i <= n;++ i)
 80         if(!dfn[i]) dfs(i);
 81 }
 82 
 83 inline void rebuild()
 84 {
 85     for(register int i = 1;i <= n;++ i)
 86     {
 87         for(register int pos = head1[i];pos;pos = edge1[pos].next)
 88         {
 89             if(x[i] != x[edge1[pos].v]) insert2(x[i], x[edge1[pos].v]);
 90         }
 91     }
 92 }
 93 
 94 int f[MAXN], ans;
 95 
 96 int dp(int u)
 97 {
 98     if(f[u]) return f[u];
 99     f[u] = size[u];
100     for(register int pos = head2[u];pos;pos = edge2[pos].next)
101         f[u] = max(f[u], dp(edge2[pos].v) + size[u]);
102     ans = max(ans, f[u]);
103     return f[u];
104 }
105 
106 int main()
107 {
108     read(n), read(r), read(c);
109     register int i, num, tmp;
110     for(i = 1;i <= n;++ i)
111     {
112         read(x[i]), read(y[i]), read(pos[i]);
113         mp[x[i]][y[i]] = i;
114     }
115     for(i = 1;i <= n;++ i)
116         row[x[i]].push_back(i);
117     for(i = 1;i <= r;++ i)
118     {
119         num = row[i].size(), tmp = 0;
120         for(register int j = 0;j < num;++ j)
121             if(pos[row[i][j]] == 1) {tmp = row[i][j];break;}
122         if(!tmp)continue;
123         for(register int j = 0;j < num;++ j)
124             if(row[i][j] == tmp)continue;
125             else if(pos[row[i][j]] == 1)insert1(tmp, row[i][j]), insert1(row[i][j], tmp);
126             else insert1(tmp, row[i][j]);
127     }
128     for(i = 1;i <= n;++ i)
129         row[x[i]].clear();
130     for(i = 1;i <= n;++ i)
131         line[y[i]].push_back(i);
132     for(i = 1;i <= c;++ i)
133     {
134         num = line[i].size(), tmp = 0;
135         for(register int j = 0;j < num;++ j)
136             if(pos[line[i][j]] == 2){tmp = line[i][j];break;}
137         if(!tmp)continue;
138         for(register int j = 0;j < num;++ j)
139             if(line[i][j] == tmp)continue;
140             else if(pos[line[i][j]] == 2)insert1(tmp, line[i][j]), insert1(line[i][j], tmp);
141             else insert1(tmp, line[i][j]);
142     }
143     for(i = 1;i <= n;++ i)
144         line[y[i]].clear();
145     for(i = 1;i <= n;++ i)
146         if(pos[i] == 3)
147         {
148             for(register int j = 0;j < 8;++ j)
149             {
150                 tmp = mp[x[i] + dx[j]][y[i] + dy[j]];
151                 if(tmp) insert1(i, tmp);
152             }
153         }
154     tarjan();
155     rebuild();
156     for(i = 1;i <= group;++ i)
157         dp(i);
158     printf("%d\n", ans);
159     return 0;
160 }
BZOJ1924

 

posted @ 2017-10-17 06:45  嘒彼小星  阅读(333)  评论(0编辑  收藏  举报