给定一个n * n 的格子,边都是导线,M秒,每秒有一根导线被烧断,问从(0,0)到(n - 1, n - 1)在第几秒后不连通?如果一直连通的话,返回-1.
输入为烧掉的边,也就A,B,C如果C= 0 ,烧掉的是(A,B) (A, B + 1) , C = 1烧掉的是(A,B) (A + 1, B)。
于是输入的就是n和3个数组。C的输入比较坑,每个数组给长度,其实A,B,C三个数组都是一样长的嘛。
数据范围: N [1..400] , M [0..2 * N * (N - 1)] A,B的范围是[0, N - 1] C里面只包含0和1。
要求复杂度: 时间 O(N^2logN) 空间 O(N^2)。
分析: 这个题可以2分时间,然后判断连通性,复杂度达到它的要求,但是我c++用dfs堆栈溢出,bfs超时,双向bfs也超时,结果用c写了一个双向bfs过了……
int e[402][402]; int mark[402][402]; int q[2][80002]; int head[2],tail[2]; int help(int num,int N,int *A,int *B, int *C) { const int dx[] = {-1, 0 , 1, 0}; const int dy[] = {0, 1, 0, -1}; int i,x,y,j,k,xx,yy; for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { e[i][j] = 15; mark[i][j] = -1; } } for (i = 0; i < num; ++i) { if (C[i]) { e[A[i]][B[i]] &= 11; e[A[i] + 1][B[i]] &= 14; } else { e[A[i]][B[i]] &= 13; e[A[i]][B[i] + 1] &= 7; } } q[0][0] = 0; q[1][0] = ((N - 1) << 9) | (N - 1); mark[0][0] = 0; mark[N - 1][N - 1] = 1; tail[0] = tail[1] = 1; head[0] = head[1] = 0; for (i = 0; ; i ^= 1) { if (head[i] == tail[i]) { return 0; } for (j = tail[i] - head[i]; j; --j) { x = q[i][head[i]] >> 9; y = q[i][head[i]++] & 511; for (k = 0; k < 4; ++k) { xx = x + dx[k]; yy = y + dy[k]; if ((xx >= 0) && (xx < N) && (yy >= 0) && (yy < N) && (e[x][y] & (1 << k)) && (mark[xx][yy] != i)) { if (mark[xx][yy] == 1 - i) { return 1; } mark[xx][yy] = i; q[i][tail[i] ++] = ((xx << 9) | yy); } } } } return 0; } int solution(int N, int A[], int M, int B[], int M2, int C[], int M3) { // write your code here... int left = 1, right = M ,mid; while (left <= right) { if (help(mid = (left + right) >> 1, N , A, B, C)) { left = mid + 1; } else { right = mid - 1; } } return (++right > M)?(-1):right; }
代码:
// you can also use includes, for example: // #include <algorithm> vector<int> f; int getf(int x) { return (x == f[x])?x:(f[x] = getf(f[x])); } void make(int x,int y) { x = getf(x); y = getf(y); if (x != y) { f[x] = y; } } int solution(int N, const vector<int> &A, const vector<int> &B, const vector<int> &C) { // write your code here... vector<vector<int> > e; int i, j, n, m = A.size(); e.resize(N); for (i = 0; i < N; ++i) { e[i].resize(N, 15); } for (i = 0; i < m; ++i) { if (C[i]) { e[A[i]][B[i]] &= 11; e[A[i] + 1][B[i]] &= 14; } else { e[A[i]][B[i]] &= 13; e[A[i]][B[i] + 1] &= 7; } } n = N * N; f.resize(n); for (i = 0; i < n; ++i) { f[i] = i; } for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if ((i + 1 < N) && (e[i][j] & 4)) { make(i * N + j, (i + 1) * N + j); } if ((j + 1 < N) && (e[i][j] & 2)) { make(i * N + j, i * N + j + 1); } } } if (getf(0) == getf(n - 1)) { return -1; } for (i = m - 1; i >= 0; --i) { if (C[i]) { make(A[i] * N + B[i], (A[i] + 1) * N + B[i]); } else { make(A[i] * N + B[i], A[i] * N + B[i] + 1); } if (getf(0) == getf(n - 1)) { break; } } return i + 1; }