这题一看很水,却做了不少时间。总觉得构图很麻烦。最后认真想想,其实并不麻烦-,- 构图始终是图论的精髓啊。---菜鸟的感叹。
/*
很裸的拓扑排序,关键只是怎么构图。考虑到每个数字的值都只会出现在特定的四个小格子里,
所以如果那四个小格子上的数不等于它自己,则与该数连一条边,说明它被覆盖掉了。最后进行
拓扑排序,如果进队列的数比总数少,说明出现环,既对应的输出broken,否则则是clean.
208K 0MS
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
string s;
int map[5][5];
bool cnt[10][10];
int deg[10];
queue <int> Q;
int dir[4][2]={{0,1},{1,0},{0,0},{1,1}};
bool toposort()
{
for(int i=1; i<=9; i++)
if(!deg[i])
Q.push(i);
int ct = 0;
while(!Q.empty())
{
int cur = Q.front();
Q.pop();
ct ++;
for(int i=1; i<=9; i++)
{
if(cnt[cur][i])
{
-- deg[i];
if(!deg[i])
Q.push(i);
}
}
}
if(ct != 9)
return false;
return true;
}
int main()
{
while(cin >> s)
{
if(s == "ENDOFINPUT")
break;
for(int i=1; i<=4; i++)
for(int j=1; j<=4; j++)
scanf("%d",&map[i][j]);
cin >> s;
memset(deg,0,sizeof(deg));
memset(cnt,0,sizeof(cnt));
while(!Q.empty())
Q.pop();
for(int i=1; i<=9; i++)
{
int sx = i / 3;
if(i % 3)
sx ++;
int sy = i % 3;
if(sy == 0) sy += 3;
for(int j = 0; j<4; j++)
{
int ex = sx + dir[j][0];
int ey = sy + dir[j][1];
if(map[ex][ey] != i && !cnt[i][map[ex][ey]])
{
cnt[i][map[ex][ey]] = true;
deg[map[ex][ey]] ++;
}
}
}
if(toposort())
printf("THESE WINDOWS ARE CLEAN\n");
else
printf("THESE WINDOWS ARE BROKEN\n");
}
return 0;
}