POJ 2582 拓扑序列,其实更为准确的说法应该是判是否出现环
这个题我是看书上解题思路做的,自己未必想的出来,就是根据他给你的窗口分布去构造图,比如说这个格子本来可以被1,2,4,5窗口共用(只是指1,2,4,5都能出现在这个格子上,但是一次当然只可能出现一种情况),现在被2占用了,那么2可能是覆盖了1,4,5窗口,这样就构造有向边<2,1>,<2,4>,<2,5>如此类推,把整个图构造出来后,出现环了 ,证明电脑坏掉了,鉴于我相当水,只好用拓扑排序写,因为一共也就9个点,尽管拓扑时间复杂度高,但数据小,也就还能接受啦,不会超时。我0MS过的。
如果可以,建议尽量用别的各种方法去判环。
这题我也WA好多次,这次是因为忘了注释freopen()函数了,各种想自残
贴代码:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 using namespace std; 5 int main() 6 { 7 char a[20]; 8 int count[20],mystack[20]; 9 bool visited[12]; 10 bool edge[12][12]; 11 string cover[4][4] = {{"1","12","23","3"},{"14","1245","2356","36"}, 12 {"47","4578","5689","69"},{"7","78","89","9"} 13 }; 14 // freopen("in.cpp","r",stdin); 15 while(~scanf("%s",a)) 16 { 17 if(strcmp(a,"ENDOFINPUT") == 0) break; 18 int w; 19 int c = 0; 20 int cur = 0,cnt = 0; 21 memset(count,0,sizeof(count)); 22 memset(visited,false,sizeof(visited)); 23 memset(edge,false,sizeof(edge)); 24 for(int i=0; i<4; i++) 25 { 26 for(int j=0; j<4; j++) 27 { 28 scanf("%d",&w); 29 if(!visited[w]) 30 { 31 visited[w] = true; 32 c++; 33 } 34 for(int k=0; k< cover[i][j].length(); k++) 35 { 36 int t = cover[i][j][k] - '0'; 37 if( t != w && !edge[w][t]) 38 { 39 if(!visited[t]) 40 { 41 visited[t] = true; 42 c++; 43 } 44 count[t]++; 45 edge[w][t] = true; 46 } 47 } 48 } 49 } 50 scanf("%s",a); 51 for(int i=1; i<=9; i++) 52 { 53 if(count[i] == 0) 54 { 55 count[i]--; 56 mystack[cur++] = i; 57 cnt++; 58 } 59 } 60 while(cur != 0) 61 { 62 cur--; 63 int t = mystack[cur]; 64 for(int k=1; k<=9; k++) 65 { 66 if(edge[t][k]) 67 count[k]--; 68 } 69 for(int i=1; i<=9; i++) 70 { 71 if(count[i] == 0) 72 { 73 count[i]--; 74 mystack[cur++] = i; 75 cnt++; 76 } 77 } 78 } 79 if(cnt < c) printf("THESE WINDOWS ARE BROKEN\n"); 80 else printf("THESE WINDOWS ARE CLEAN\n"); 81 } 82 return 0; 83 }