【图论】[POJ 2942]Knights of the Round Table

先找连通图,然后检查是否是二分图注意如果是在线的算法记得要清空Color数组因为存在一种情况儿子中含有两个连通图,那么自己儿子中就会存在一个割点已经被染了色,就有可能存在冲突。

#include <cstdio>
#include <algorithm>
#include <stack>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 1000;
const int MAXM = 1000000;
vector<int> vec;
struct node {
    int v;
    node *next;
}Edges[MAXM*2+10], *adj[MAXN+10], *ecnt=Edges;
void addedge(int u, int v){
    ++ecnt;
    ecnt->v = v;
    ecnt->next = adj[u];
    adj[u] = ecnt;
}
int dfn[MAXN+10], low[MAXN+10], dcnt;
int kcnt, Color[MAXN+10], from[MAXN+10];
bool vis[MAXN+10]; bool Mp[MAXN+2][MAXN+2];
bool check(int u, int id, int c){
    Color[u]=c;
    for(node *p=adj[u];p;p=p->next) if(from[p->v] == id){
        if(Color[p->v] && Color[p->v] == Color[u])
            return false;
        if(!Color[p->v] && !check(p->v, id, 3-c))
            return false;
    }
    return true;
}
stack<int> sta;
void dfs(int u, int fa){
    dfn[u] = low[u] = ++dcnt; sta.push(u);
    for(node *p=adj[u];p;p=p->next){
        int v = p->v;
        if(!dfn[v]){
            dfs(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u]){
                ++kcnt;
                vec.clear();
                int tmp;
                do{
                    vec.push_back( sta.top() );
                    from[(tmp=sta.top())] = kcnt;
                    sta.pop(); Color[tmp] = 0;
                }while(tmp != v);
                vec.push_back(u);
                int Len = vec.size();
                if(!check(u, kcnt, 1) && Len >= 3){
                    for(int j=0;j<Len;j++)
                        vis[vec[j]] = true;
                }
            }
        }else if(v!=fa)
            low[u] = min(low[u], dfn[v]);
    }
}
int first;
bool solve(){
    int n, m, u, v;
    scanf("%d%d", &n, &m);
    if(!n && !m) return false;
    ecnt = Edges;
    memset(adj, 0, sizeof adj);
    memset(dfn, 0, sizeof dfn);
    memset(low, 0, sizeof low);
    memset(vis, 0, sizeof vis);
    memset(Color, 0, sizeof Color);
    memset(Mp, 0, sizeof Mp);
    memset(from, 0, sizeof from);
    dcnt = 0; kcnt = 0;
    while(!sta.empty()) sta.pop();
    for(int i=0;i<m;i++){
        scanf("%d%d", &u, &v);
        Mp[u][v] = Mp[v][u] = true;
    }
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            if(!Mp[i][j]){
                addedge(i, j);
                addedge(j, i);
            }
    int ans = n;
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i, -1);
    for(int i=1;i<=n;i++)
        if(vis[i]) 
            ans--;
    printf("%d\n", ans);
    return true;
}
int main(){
    while(solve());

    return 0;
}

posted on 2015-07-23 11:08  JeremyGuo  阅读(134)  评论(0编辑  收藏  举报

导航