[双连通] poj 2942 Knights of the Round Table#双连通+交叉染色

来源:互联网 发布:mysql 清空整个数据库 编辑:程序博客网 时间:2024/06/03 09:30
/**[双连通] poj 2942 Knights of the Round Table#割点+交叉染色题意,N个骑士中某些骑士之间会有仇恨。骑士们开会时围坐在一个圆桌旁。一次会议能够举行,当且仅当没有相邻的两个骑士相互仇恨,且开会人数为大于2的奇数。若某个骑士任何会议都不能参加,那么就必须将它踢出。给出骑士之间的仇恨关系,问需要踢出多少个骑士。建立输入图的补图,即没有仇恨关系的骑士建边Trajan算法找割点并记录双强连通分量;交叉染色搜索奇圈。若某块存在奇圈,那么该块中的所有点都存在于奇圈中,否则,全部删除*/#include <stdio.h>#include <string.h>#include <vector>#include <algorithm>using namespace std;#define N 1024vector<int> g[N];int dfn[N],color[N],low[N],stk[N],sp,used[N],typ,id[N];bool mat[N][N],vis[N];int m,n;bool bicolor(int u,int f,int cc){    color[u] = cc;    for(int i = 0; i < g[u].size(); ++i)    {        int v = g[u][i];        if(id[v] != id[u] || u == f)            continue;        if(color[v] == cc || (!color[v] && bicolor(v,u,-cc)))            return 1;    }    return 0;}void dfs(int u,int f,int dep){    vis[u] = 1;    low[u] = dfn[u] = dep;    stk[sp++] = u;    for(int i = 0; i < g[u].size(); ++i)    {        int v = g[u][i];        if(vis[v] && v != f)            low[u] = min(low[u],dfn[v]);        if(vis[v] == 0)        {            dfs(v,u,dep+1);            low[u] = min(low[u],low[v]);            if(low[v] >= dfn[u])            {                int t,k = 0;                do{                    k++;                    id[t = stk[--sp]] = typ;                }while(t != v);                id[u] = typ;                memset(color,0,sizeof(color));                if(k >= 2 && bicolor(u,0,1))  ///至少三人才可以                    for(int j = 1; j <= n; ++j)                        if(id[j] == typ)                            used[j]  = 1;                ++typ;            }        }    }}int main(){    int i,j;    while(scanf("%d%d",&n,&m) != EOF && n)    {        memset(used,0,sizeof(used));        memset(mat,0,sizeof(mat));        memset(vis,0,sizeof(vis));        memset(id,0,sizeof(id));        memset(g,0,sizeof(g));        while(m--)        {            scanf("%d%d",&i,&j);            mat[i][j] = mat[j][i] = 1;        }        for(i = 1; i <= n; ++i)            for(j = 1; j <= n; ++j)                if(i != j && !mat[i][j])                    g[i].push_back(j);        sp = 0;        typ = 1;        for(i = 1; i <= n; ++i)            if(!vis[i])                dfs(i,0,1);        int res = 0;        for(i = 1; i <= n; ++i)            res += !used[i];        printf("%d\n",res);    }    return 0;}