BZOJ1924: [Sdoi2010]所驼门王的宝藏
1924: [Sdoi2010]所驼门王的宝藏
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 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
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 }