IT民工
加油!

参考了题解将这题的代码写了一遍,整体来说收获还是比较大的。用邻接矩阵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;
}

 

 

 

 

posted on 2012-07-29 15:49  找回失去的  阅读(239)  评论(0)    收藏  举报