POJ 2942 Knights of the Round Table

参考了题解将这题的代码写了一遍,整体来说收获还是比较大的。用邻接矩阵g存骑士的关系,

相互憎恨就连一条边。然后建立图g的补图,这里用邻接表会更好,表示这些骑士是可以相邻

的。然后用tarjan算法求补图的双连通分量,注意题目要求骑士g要在奇圈中。

传送门:http://blog.csdn.net/lyy289065406/article/details/6756821 

有详细分析过程,膜拜下。

/*Accepted    8468K    1266MS    C++    2516B    2012-07-29 15:29:42*/

#include<cstdio>

#include<cstring>

#include<cstdlib>

const int MAXN = 1 << 10;

const int MAXM = MAXN * MAXN;



int v[MAXM], first[MAXM], next[MAXM], s[MAXN], dfn[MAXN], low[MAXN];

int remain[MAXN], color[MAXN], recolor[MAXN], g[MAXN][MAXN];

int N, M, e, top, col, cnt;



void addedge(int x, int y)

{

    v[e] = y;

    next[e] = first[x], first[x] = e ++;

}



int dfs(int cur, int c)

{

    recolor[cur] = c;

    for(int i = first[cur]; i != -1; i = next[i])

    {

        if(color[v[i]] == color[cur])

        {

            if(recolor[v[i]])

            {

                if(recolor[v[i]] == c)

                    return 1;

            }

            else if(dfs(v[i], -c))

                return 1;

        }

    }

    return 0;

}



void tarjan(int cur)

{

    int i, j, k;

    low[cur] = dfn[cur] = ++ cnt;

    s[top ++] = cur;

    for(i = first[cur]; i != -1; i = next[i])

    {

        if(!dfn[v[i]])

        {

            tarjan(v[i]);

            if(low[v[i]] < low[cur])

                low[cur] = low[v[i]];

            else if(low[v[i]] == dfn[cur])

            {

                ++ col;

                for(j = top; s[j] != v[i]; )

                    color[s[-- j]] = col;

                color[cur] = col;

                memset(recolor, 0, sizeof recolor);

                if(dfs(cur, 1))

                {

                    for(k = j; k < top; k ++)

                        remain[s[k]] = 1;

                    remain[cur] = 1;

                }

                top = j;

            }

        }

        else if(dfn[v[i]] < low[cur])

            low[cur] = dfn[v[i]];

    }

}



void ReadGraph()

{

    int i, j, x, y;

    memset(g, 0, sizeof g);

    for(i = 0; i < M; i ++)

    {

        scanf("%d%d", &x, &y);

        g[x][y] = g[y][x] = 1;

    }

    memset(first, -1, sizeof first);

    e = 0;

    for(i = 1; i <= N; i ++)

        for(j = i + 1; j <= N; j ++)

            if(!g[i][j])

                addedge(i, j), addedge(j, i);

}



void solve()

{

    int i, ans = 0;

    top = cnt = col = 0;

    memset(dfn, 0, sizeof dfn);

    memset(color, 0, sizeof color);

    memset(remain, 0, sizeof remain);

    for(i = 1; i <= N; i ++)

        if(!dfn[i])

            tarjan(i);

    for(i = 1; i <= N; i ++)

        if(remain[i] == 0)

            ++ ans;

    printf("%d\n", ans);

}



int main()

{

    while(scanf("%d%d", &N, &M), N || M)

    {

        ReadGraph();

        solve();

    }

    return 0;

}

 

 

 

 

你可能感兴趣的:(table)