poj 2585,zoj 2193 Window Pains【拓扑排序思想判断图是否存在环】

解题报告参见《图论算法理论、实现及应用》 王桂平主编 北京大学出版社 P74。

View Code
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
using namespace std;

const string end = "ENDOFINPUT";
string cover[4][4]; //表示能覆盖(i,j)位置的窗口的集合。
int mp[5][5];   //屏幕快照上最后显示的内容。
bool g[10][10]; //邻接表。
bool exist[10]; //某个窗口是否在屏幕快照上出现。
int tot; //记录屏幕上总共出现的不同的窗口种类,以这些窗口为顶点,构建有向图。
int id[10]; //入度。

//初始化操作。 统计覆盖(i,j)位置的窗口的集合。
void calc()
{
    for(int k = 1; k <= 9; k++) {
        int i = (k-1)/3;
        int j = (k-1)%3;
        cover[i][j] += (k + '0');    //第k个窗口左上角位置。
        cover[i+1][j] += (k + '0'); //第k个窗口右上角位置。
        cover[i][j+1] += (k + '0'); //第k个窗口左下角位置。
        cover[i+1][j+1] += (k + '0'); //第k个窗口右下角位置。
    }
}

void build() //构建有向图。
{
    memset(g, 0, sizeof(g));
    memset(id, 0, sizeof(id));
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            int len = cover[i][j].length();
            for(int p = 0; p < len; p++) {
                if( !g[mp[i][j]][cover[i][j][p] - '0'] && mp[i][j] != cover[i][j][p] - '0') {
                    g[mp[i][j]][cover[i][j][p] - '0'] = 1;
                    id[cover[i][j][p] - '0']++;
                }
            }
        }
    }
}

bool check() //判断有向图是否存在有向环。拓扑排序思想。
{
    for(int k = 0; k < tot; k++) {
        int i = 1;
        //统计出现在屏幕快照中、并且入度不为0的窗口个数。
        while( !exist[i] || (i <= 9 && id[i] > 0) ) {
            i++;
        } 

        //i>9说明所有窗口入度均不为0,则必存在环。
        if(i > 9) {
            return 0;
        }

        //处理编号为i的窗口,删除该窗口以及其相应出边。
        exist[i] = 0;
        for(int j = 1; j <= 9; j++) {
            //删除相应顶点入边(入度减1)。
            if(exist[j] && g[i][j]) {
                id[j]--;
            }
        }
    }
    return 1;
}

int main()
{
    calc();

    string str;
    while(cin >> str) {

        if(str == end) {
            break;
        }

        memset(exist, 0, sizeof(exist));
        tot = 0; //tot为屏幕快照中出现的窗口种类的个数。
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++) {
                scanf("%d", &mp[i][j]);
                if( !exist[mp[i][j]] ) {
                    tot++;
                }
                exist[mp[i][j]] = true;
            }
        }

        cin >> str;
        build();

        if( check() ) {
            printf("THESE WINDOWS ARE CLEAN\n");
        } else {
            printf("THESE WINDOWS ARE BROKEN\n");
        }
    }
    return 0;
}

 

posted @ 2012-07-25 23:26  小猴子、  阅读(303)  评论(0编辑  收藏  举报