[拓扑排序] PKU 2585 Window Pains
拓扑排序判断有向图是否有环,1A啊!!!
对每个位置(前3行前3列),如果它控制范围内的某个位置上为 j ,而这个位置原始值为 i ,则添加一条 i 到 j 的边,如果出现环则说明电脑出问题了;
不知道数据中是否含有非法的,所以就加了个判断:判断是否出现了非法状态,即某个位置出现了不属于这个位置的数字。
# include <cstdio> # include <cstring> # define N 5 # define NS ((N-1)*(N-1)) + 1 const int n = 3; const int m = 9; int in[NS]; int f[N][N]; char g[NS][NS]; void add(int i, int j) { if (!g[j][i]) { g[j][i] = 1; ++in[i]; } } void build(void) { memset(g, 0, sizeof(g)); memset(in, 0, sizeof(in)); int i, j, t, k; for (i = 1; i <= n; ++i) for (j = 1; j <= n; ++j) { k = j+(i-1)*n; if (f[i][j] != k) add(f[i][j] ,k); if (f[i+1][j] != k) add(f[i+1][j] ,k); if (f[i][j+1] != k) add(f[i][j+1] ,k); if (f[i+1][j+1] != k) add(f[i+1][j+1] ,k); } } int topsort(void) { int cnt = 0; char vis[NS]; memset(vis, 0, sizeof(vis)); //for(int i = 1; i <= m; ++i) printf("indegrees[%d] = %d\n", i, in[i]); while (cnt < m) { int c = 0; for (int i = 1; i <= m; ++i) if(!vis[i] && !in[i]) { ++c; vis[i] = 1; for (int j = 1; j <= m; ++j) if (g[i][j]) --in[j]; break; } if (c == 0) return -1; ++cnt; } return 0; } bool check(void) { if(f[1][1] != 1 && f[1][n+1] != 3 || f[n+1][1] != 7 || f[n+1][n+1] != 9) { return false; } if (f[1][2]!=1 && f[1][2]!=2) {return false;} if (f[2][1]!=1 && f[2][1]!=4) {return false;} if (f[1][3]!=2 && f[1][3]!=3) {return false;} if (f[3][1]!=4 && f[3][1]!=7) {return false;} if (f[2][2]!=1 && f[2][2]!=2 && f[2][2]!=4 && f[2][2]!=5) {return false;} if (f[2][3]!=2 && f[2][3]!=3 && f[2][3]!=5 && f[2][3]!=6) {return false;} if (f[3][2]!=7 && f[3][2]!=8 && f[3][2]!=4 && f[3][2]!=5) {return false;} if (f[3][3]!=9 && f[3][3]!=6 && f[3][3]!=5 && f[3][3]!=8) {return false;} } void solve() { if (check() == false) { puts("THESE WINDOWS ARE BROKEN"); return ; } int ans = topsort(); if (ans == -1) puts("THESE WINDOWS ARE BROKEN"); else puts("THESE WINDOWS ARE CLEAN"); } int main() { char s[20]; while (scanf("%s", s), strcmp(s, "ENDOFINPUT")!=0) { for (int i = 1; i <= n+1; ++i) for (int j = 1; j <= n+1; ++j) scanf("%d", &f[i][j]); build(); solve(); scanf("%s", s); } return 0; }
直接DFS判断是否有环应该也可行。