UvaLive3523 Knights of the Round Table(点双联通分量+二分图染色)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UvaLive3523 Knights of the Round Table(点双联通分量+二分图染色)相关的知识,希望对你有一定的参考价值。

UvaLive3523 Knights of the Round Table

参考了Kuangbin巨的题解。

/* POJ 2942 Knights of the Round Table 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1、 相互憎恨的两个骑士不能坐在直接相邻的2个位置; 2、 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。 注意:1、所给出的憎恨关系一定是双向的,不存在单向憎恨关系。 2、由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士。 即每个骑士的座位两边都必定各有一个骑士。 3、一个骑士无法开会,就是说至少有3个骑士才可能开会。 首先根据给出的互相憎恨的图中得到补图。 然后就相当于找出不能形成奇圈的点。 利用下面两个定理: (1)如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈), 那么这个双连通分量的其他顶点也在某个奇圈中; (2)如果一个双连通分量含有奇圈,则他必定不是一个二分图。反过来也成立,这是一个充要条件。 所以本题的做法,就是对补图求点双连通分量。 然后对于求得的点双连通分量,使用染色法判断是不是二分图,不是二分图,这个双连通分量的点是可以 存在的 */

技术分享
/*
ID: onlyazh1
LANG: C++
TASK: Knights of the Round Table
*/

#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<cctype>
#include<vector>
#include<cstring>
#include<fstream>
#include<iomanip>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;

const int MAXN=1010;
const int MAXM=1000010;
int n,m,u,v,tot;
int low[MAXN];
int dfn[MAXN];
int head[MAXN];
int Stack[MAXN];
int tmp[MAXN];
int color[MAXN];
bool ok[MAXN];
bool can[MAXN];
bool instack[MAXN];
bool G[MAXN][MAXN];
int idx,top,cc;
struct Edge{
    int v,nex;
}edge[MAXM<<1];

void addedge(int u,int v){
    edge[tot].v=v;
    edge[tot].nex=head[u];
    head[u]=tot++;
}

bool dfs(int u,int col){
    color[u]=col;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        int v=edge[i].v;
        if(!ok[v]) continue;
        if(color[v]!=-1){
            if(color[v]==col) return false;
            continue;
        }
        if(!dfs(v,!col)) return false;
    }
    return true;
}

void Tarjan(int u,int pre){
    low[u]=dfn[u]=++idx;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].nex){
        int v=edge[i].v;
        if(v==pre) continue;
        if(!dfn[v]){
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                int vn,cc=0;
                memset(ok,false,sizeof(ok));
                do{
                    vn=Stack[--top];
                    ok[vn]=true;
                    tmp[cc++]=vn;
                    instack[vn]=false;
                }while(vn!=v);
                ok[u]=true;
                memset(color,-1,sizeof(color));
                if(!dfs(u,0)){
                    can[u]=true;
                    while(cc--) can[tmp[cc]]=true;
                }
            }
        }
        else if(instack[v])
            low[u]=min(low[u],dfn[v]);
    }
}

void init(){
    tot=top=idx=0;
    memset(G,false,sizeof(G));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(can,false,sizeof(can));
    memset(head,-1,sizeof(head));
    memset(instack,false,sizeof(instack));
}
int main(){
    ifstream cin("in.txt");
    while(cin>>n>>m&&n+m){
        init();
        while(m--){
            cin>>u>>v;
            G[u][v]=G[v][u]=true;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j&&!G[i][j])
                    addedge(i,j);

        for(int i=1;i<=n;i++)
            if(!dfn[i]) Tarjan(i,i);
        cout<<"***"<<endl;
        int ans=0;
        for(int i=1;i<=n;i++)
            if(!can[i]) ans++;
        cout<<ans<<endl;
    }
    return 0;
}
View Code

 

以上是关于UvaLive3523 Knights of the Round Table(点双联通分量+二分图染色)的主要内容,如果未能解决你的问题,请参考以下文章

[Usaco2005 Dec]Knights of Ni 骑士

poj 2942 Knights of the Round Table - Tarjan

Knights of a Polygonal Table(骑士的多角桌)

poj2942 Knights of the Round Table

POJ 2942Knights of the Round Table(双联通分量+染色判奇环)

POJ 2942Knights of the Round Table(二分图判定+双连通分量)