POJ 2942 点双联通+二分图染色

来源:互联网 发布:如何正确下载软件 编辑:程序博客网 时间:2024/04/20 11:13

点击打开链接

题意:给n个骑士和m对关系,关系是互相仇恨,现在召开一个圆桌会议,要求相邻的两个人不能有仇恨关系,问有多少骑士不管怎么分配都不能参加会议

思路:白书上的经典例题

#include <stack>#include <vector>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const ll INF=0x3f3f3f3f3f3f3f3fll;const int maxn=1010;//注意点的编号从0开始的struct edge{    int u,v;    edge(int a,int b){u=a;v=b;}};int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt,n,m;vector<int>G[maxn],bcc[maxn];stack<edge>S;int dfs(int u,int fa){    int lowu=pre[u]=++dfs_clock;    int child=0;    for(unsigned int i=0;i<G[u].size();i++){        int v=G[u][i];        edge e=edge(u,v);        if(!pre[v]){            S.push(e);child++;            int lowv=dfs(v,u);            lowu=min(lowv,lowu);            if(lowv>=pre[u]){                iscut[u]=1;bcc_cnt++;bcc[bcc_cnt].clear();                while(1){                    edge x=S.top();S.pop();                    if(bccno[x.u]!=bcc_cnt) bcc[bcc_cnt].push_back(x.u),bccno[x.u]=bcc_cnt;                    if(bccno[x.v]!=bcc_cnt) bcc[bcc_cnt].push_back(x.v),bccno[x.v]=bcc_cnt;                    if(x.u==u&&x.v==v) break;                }            }        }else if(pre[v]<pre[u]&&v!=fa){            S.push(e);            lowu=min(lowu,pre[v]);        }    }    if(fa<0&&child==1) iscut[u]=0;    return lowu;}void find_bcc(){    memset(pre,0,sizeof(pre));    memset(iscut,0,sizeof(iscut));    memset(bccno,0,sizeof(bccno));    dfs_clock=0;bcc_cnt=0;    for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1);}bool vis[maxn][maxn];int odd[maxn],color[maxn];bool bipartite(int u,int b){    for(unsigned int i=0;i<G[u].size();i++){        int v=G[u][i];        if(bccno[v]!=b) continue;        if(color[v]==color[u]) return 0;        if(!color[v]){            color[v]=3-color[u];            if(!bipartite(v,b)) return 0;        }    }    return 1;}int main(){    int u,v;    while(scanf("%d%d",&n,&m)!=-1){        if(n==0&&m==0) break;        for(int i=0;i<maxn;i++) G[i].clear();        memset(vis,0,sizeof(vis));        memset(odd,0,sizeof(odd));        while(m--){            scanf("%d%d",&u,&v);u--;v--;            vis[u][v]=1;vis[v][u]=1;        }        for(int i=0;i<n;i++)            for(int j=i+1;j<n;j++) if(!vis[i][j]) G[i].push_back(j),G[j].push_back(i);        find_bcc();        for(int i=1;i<=bcc_cnt;i++){            memset(color,0,sizeof(color));            for(unsigned int j=0;j<bcc[i].size();j++) bccno[bcc[i][j]]=i;            int u=bcc[i][0];color[u]=1;            if(!bipartite(u,i)) for(int j=0;j<bcc[i].size();j++) odd[bcc[i][j]]=1;        }        int sum=0;        for(int i=0;i<n;i++) if(odd[i]) sum++;        printf("%d\n",n-sum);    }    return 0;}

0 0
原创粉丝点击