poj 2942--Knights of the Round Table (点双连通分量)

来源:互联网 发布:sai绘画软件手机版 编辑:程序博客网 时间:2024/06/11 15:47

题目链接点这里


有个奇特但显然的结论,如何一个双联通分量中有奇圈,那这个双联通分量中的所有点都都可以处于奇圈上

证明的话可以这样

任选一个点x,如果x点在那个奇圈上,显然成立

如果不是,我们可以从x点,构造2条路径到奇圈上的不同两个a,b点。显然a,b之间的在奇圈上的路径,有2条,分别为奇数长度和偶数长度。

如果xa+xb为奇数,那么就选取ab的偶数路径,反之选取奇数路径。就一定可以构造一个经过x的奇圈

#include<iostream>#include<map>#include<stdio.h>#include<bitset>#include<stack>#include<algorithm>#include<queue>#include<set>#include<string.h>#include<string>#include<vector>#define MX 1111#define INF 0x3f3f3f3f#define mem(x,y) memset(x,y,sizeof(x))#define FIN freopen("input.txt","r",stdin)using namespace std;int n,m;int head[MX],cnt;struct Edge {    int nxt,to;} edge[2*MX*MX];void edge_init() {    mem(head,-1);    cnt=0;}void edge_add(int a,int b) {    edge[cnt].to=b;    edge[cnt].nxt=head[a];    head[a]=cnt++;}/*int low[MX],pre[MX],dfs_block;bool iscut[MX];int dfs(int u,int fa){    int lowu=pre[u]=++dfs_block;    int child=0;    for(int i=head[u]; ~i; i=edge[i].nxt)    {        int v=edge[i].to;        if(!pre[v])        {            child++;            int lowv=dfs(v,u);            lowu=min(lowu,lowv);        }        else if(pre[v]<pre[u]&&v!=fa) lowu=min(lowu,pre[v]);    }    if(lowu>=pre[u]) iscut[u]=1;    if(fa<0&&child==1) iscut[u]=0;    return low[u]=lowu;}void cut_v(){    dfs_block=0;    mem(pre,0);    mem(low,0);    mem(iscut,0);    for(int i=1; i<=n; i++)        if(!pre[i]) dfs(i,-1);}*/int low[MX],pre[MX],bccno[MX],dfs_block,bcc_cnt;bool iscut[MX];//bitset<MX> bcc[MX];vector<int>bcc[MX];stack<int> S;int dfs(int u,int fa) {    int lowu=pre[u]=++dfs_block;    int child=0;    for(int i=head[u]; ~i; i=edge[i].nxt) {        int v=edge[i].to;        if(!pre[v]) {            S.push(i);            child++;            int lowv=dfs(v,u);            lowu=min(lowu,lowv);            if(lowv>=pre[u]) {                iscut[u]=1;                bcc_cnt++;                //bcc[bcc_cnt].reset();                bcc[bcc_cnt].clear();                while(1) {                    int w=S.top();                    S.pop();                    int vv=edge[w].to,uu=edge[w^1].to;                    if(bccno[uu]!=bcc_cnt) {                        //bcc[bcc_cnt][uu]=1;                        bcc[bcc_cnt].push_back(uu);                        bccno[uu]=bcc_cnt;                    }                    if(bccno[vv]!=bcc_cnt) {                        // bcc[bcc_cnt][vv]=1;                        bcc[bcc_cnt].push_back(vv);                        bccno[vv]=bcc_cnt;                    }                    if(vv==v&&uu==u) break;                }            }        } else if(pre[v]<pre[u]&&v!=fa) {            lowu=min(lowu,pre[v]);        }    }    if(fa<0&&child==1) iscut[u]=0;    return low[u]=lowu;}void find_bcc() {    dfs_block=bcc_cnt=0;    mem(pre,0);    mem(low,0);    mem(iscut,0);    mem(bccno,0);    for(int i=1; i<=n; i++)        if(!pre[i]) dfs(i,-1);}bool isok[MX][MX];inline int read() {    int ret=0,c,f=1;    for(c=getchar(); !(isdigit(c)||c=='-'); c=getchar());    if(c=='-') f=-1,c=getchar();    for(; isdigit(c); c=getchar()) ret=ret*10+c-'0';    if(f<0) ret=-ret;    return ret;}bool is[MX];int color[MX];bool color_dfs(int u,int col,int w) {    if((color[u]|1)!=(col|1)) color[u]=-1;    else if(color[u]!=-1&& color[u]!=col) return 0;    if(color[u]!=-1) return 1;    color[u]=col; //cout<<u<<endl;    for(int i=head[u]; ~i; i=edge[i].nxt) {        int v=edge[i].to;        if(!bcc[w][v]) continue;// cout<<u<<" "<<v<<endl;        if(color_dfs(v,col^1,w)==0) return 0;    }    return 1;}void ok(int u,int w) {    if(is[u]) return;    is[u]=1;    for(int i=head[u]; ~i; i=edge[i].nxt) {        int v=edge[i].to;        if(!bcc[w][v]) continue;        ok(v,w);    }    return;}int main() {    FIN;    while(scanf("%d%d",&n,&m)==2&&n) {        edge_init();        mem(isok,1);        for(int i=1; i<=m; i++) {            int a,b;            a= read(),b=read();            if(a>b) swap(a,b);            isok[a][b]=0;        }        for(int i=1; i<=n; i++)for(int j=1; j<i; j++) if(isok[j][i]) edge_add(i,j),edge_add(j,i);        find_bcc();        mem(is,0);        int w=0;        mem(color,-1);        for(int i=1; i<=n; i++)            if(color[i]==-1) {                if(!color_dfs(i,w,bccno[i])) ok(i,bccno[i]);                w+=2;            }        int cnnt=0;        for(int i=1; i<=n; i++) if(!is[i]) {                cnnt++;            }        printf("%d\n",cnnt);    }    return 0;}


0 0
原创粉丝点击