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
这题做法挺多的吧
首先行和列的处理方法就有很多种
第一种 开虚点 第二种 找到一个行(列)门, 它跟行(列)门连双向边,其他连单向边
至于九宫格的门 直接开map乱连边就好了
然后缩环 然后dp求最长链 非常朴素的思路
我的代码略长 3K 不过1A了2333
我的代码略长 3K 不过1A了2333
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int maxm = 1000010;
inline int read()
{
int tmp = 0;
char ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) tmp = tmp * 10 + ch - '0', ch = getchar();
return tmp;
}
int n, r, c, head[maxn], Head[maxn], cnt, Cnt, ans;
int x[maxn], y[maxn], type[maxn], dfn[maxn], low[maxn], tim, st[maxn], top;
int scc[maxn], num, dp[maxn], size[maxn], q[maxn], ql, qr, d[maxn];
int dx[ 9 ] = { 0, 1, 1, 1, 0, 0, -1, -1, -1 };
int dy[ 9 ] = { 0, 1, 0, -1, 1, -1, 1, 0, -1 };
map < int, int > mp[maxm];
map < pair< int, int >, bool > M;
vector < int > X[maxm], Y[maxm];
struct edge { int to, nxt; } e[ maxm ], E[ maxm ];
inline void addedge(int x, int y) { if( x ^ y ) { e[ ++cnt ].to = y; e[ cnt ].nxt = head[ x ]; head[ x ] = cnt; } }
inline void Addedge(int x, int y) { if( x ^ y ) { E[ ++Cnt ].to = y; E[ Cnt ].nxt = Head[ x ]; Head[ x ] = Cnt; d[ y ]++; } }
void dfs(int x)
{
int tmp = 0;
dfn[ x ] = low[ x ] = ++tim;
st[ ++top ] = x;
for( int i = head[ x ] ; i ; i = e[ i ].nxt )
{
int y = e[ i ].to;
if( !dfn[ y ] ) dfs( y ), low[ x ] = min( low[ x ], low[ y ] );
else if( !scc[ y ] ) low[ x ] = min( low[ x ], dfn[ y ] );
}
if( low[ x ] == dfn[ x ] )
{
num++;
while( tmp ^ x )
{
tmp = st[ top-- ];
scc[ tmp ] = num;
size[ num ]++;
}
}
}
inline void rebuild()
{
for( int x = 1 ; x <= n ; x++ )
for( int i = head[ x ] ; i ; i = e[ i ].nxt )
{
int y = scc[ x ], z = scc[ e[ i ].to ];
if( ( y ^ z ) && !M[ make_pair( y, z ) ] )
Addedge( y, z ), M[ make_pair( y, z ) ] = true;
}
}
inline void topu()
{
for( int i = 1 ; i <= num ; i++ )
dp[ i ] = size[ i ];
for( int i = 1 ; i <= num ; i++ )
if( !d[ i ] ) q[ ++qr ] = i;
while( ql ^ qr )
{
int x = q[ ++ql ];
ans = max( ans, dp[ x ] );
for( int i = Head[ x ] ; i ; i = E[ i ].nxt )
{
int y = E[ i ].to;
dp[ y ] = max( dp[ y ], dp[ x ] + size[ y ] );
if( !--d[ y ] ) q[ ++qr ] = y;
}
}
}
int main()
{
n = read(), r = read(), c = read();
for( int i = 1 ; i <= n ; i++ )
{
x[ i ] = read(), y[ i ] = read(), type[ i ] = read();
X[ x[ i ] ].push_back( i );
Y[ y[ i ] ].push_back( i );
mp[ x[ i ] ][ y[ i ] ] = i;
}
for( int i = 1 ; i <= r ; i++ )
{
int tmp = 0, size = X[ i ].size();
for( int j = 0 ; j < size ; j++ )
if( type[ X[ i ][ j ] ] == 1 ) { tmp = X[ i ][ j ]; break; }
if( tmp )
for( int j = 0 ; j < size ; j++ )
{
addedge( tmp, X[ i ][ j ] );
if( type[ X[ i ][ j ] ] == 1 ) addedge( X[ i ][ j ], tmp );
}
}
for( int i = 1 ; i <= c ; i++ )
{
int tmp = 0, size = Y[ i ].size();
for( int j = 0 ; j < size ; j++ )
if( type[ Y[ i ][ j ] ] == 2 ) { tmp = Y[ i ][ j ]; break; }
if( tmp )
for( int j = 0 ; j < size ; j++ )
{
addedge( tmp, Y[ i ][ j ] );
if( type[ Y[ i ][ j ] ] == 2 ) addedge( Y[ i ][ j ], tmp );
}
}
for( int i = 1 ; i <= n ; i++ )
if( type[ i ] == 3 )
for( int j = 1 ; j <= 8 ; j++ )
if( mp[ x[ i ] + dx[ j ] ][ y[ i ] + dy[ j ] ] )
addedge( i, mp[ x[ i ] + dx[ j ] ][ y[ i ] + dy[ j ] ] );
for( int i = 1 ; i <= n ; i++ )
if( !dfn[ i ] ) dfs( i );
rebuild();
topu();
return printf( "%d\n", ans ), 0;
}