首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

[点双接通分量-奇环判定]poj 2942:Knights of the Round Table

2012-11-04 
[点双连通分量-奇环判定]poj 2942:Knights of the Round Table大致题意:? ? 给出一个无向图,求出这个图的

[点双连通分量-奇环判定]poj 2942:Knights of the Round Table

大致题意:

? ? 给出一个无向图,求出这个图的补图G。求出在G中存在多少个点使得这些点不属于任何一个奇环中。

?

大致思路:
? ? 这道题从一开始就是个杯具!先是把题目想成边的双连通分量做,狂哇。后来用割点的模版照着网上的代码改造出一个点双连通分量的代码,依然哇!!原因是同一个点可能属于不同的点双连通分量!! ? 后来把搜索染色的过程加到Tarjan里面,还是哇!!检查出来原因是搜索u的时候,起点并没有标记其在那一块双连通分量!! ?前前后后花了我八天才AC……大概得终身难忘这道题了>_< ? 发图供大牛BS


[点双接通分量-奇环判定]poj 2942:Knights of the Round Table

?

给出一组可以判边双连通分量死刑的数据


[点双接通分量-奇环判定]poj 2942:Knights of the Round Table

?

#include<iostream>#include<cstdio>#include <algorithm>#include<cstring>using namespace std;const int inf=1<<30;const int nMax=30015;const int mMax=5000000;class edge{public:    int u,v,nex;};edge e[mMax];int k,k1,head[nMax];//head[i]是以点i为起点的链表头部int dfn[nMax],low[nMax],sta[nMax],top,atype,belon[nMax],dep;   //Tarjan需要的数据记录 //atype 强连通分量的个数bool insta[nMax];int n,m;int ans,vis[nMax],num[nMax];void addedge(int a,int b){    e[k].u=a;    e[k].v=b;    e[k].nex=head[a];    head[a]=k;k++;}int change(int a){    if(a==1)return 2;    if(a==2)return 1;    return 0;}int clor[nMax],cnt;bool dfs(int loc,int val){    int i,v;    clor[loc]=val;    for(i=head[loc];i;i=e[i].nex){        v=e[i].v;        if(atype!=belon[v])continue;        if(clor[v]==0){            if(!dfs(v,change(val))){                return 0;            }        }        else{            if(clor[v]!=change(clor[loc])){                return 0;            }        }    }    return 1;}void Tarjan(int u,int rt){                 //我的Tarjan模版    int i,t;    dfn[u]=low[u]=++dep;    sta[++top]=u;    insta[u]=1;    for(i=head[u];i;i=e[i].nex){        int v=e[i].v;        if(v==rt)continue;        if(!dfn[v]){            Tarjan(v,u);            low[u]=min(low[u],low[v]);            if(dfn[u]<=low[v]){     ///要注意一个点可能同时属于不同的点双连通分量                atype++;              //点双通分量个数                do{                    t=sta[top--];                    insta[t]=0;                    belon[t]=atype;   //第j个点属于第atype个连通块                    num[++cnt]=t;                }while(v!=t);                num[++cnt]=u;                memset(clor,0,sizeof(clor));                if(cnt>=3&&!dfs(u,1)){                     while(cnt>0)                        vis[num[cnt--]]=1;                }                else cnt=0;            }        }        else{            if(insta[v])low[u]=min(low[u],dfn[v]);        }    }}void init(){    k=k1=1;    dep=1;    top=atype=0;    memset(insta,0,sizeof(insta)); //是否在栈中    memset(head,0,sizeof(head));   //静态链表头指针    memset(low,0,sizeof(low));     //Tarjan的low数组    memset(dfn,0,sizeof(dfn));     //Tarjan的dfn数组    memset(belon,0,sizeof(belon)); //记录每个点属于哪一个双连通分量}bool map[2000][2000];int main(){    int i,j,a,b;    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){        init();        ans=0;        cnt=0;        memset(map,0,sizeof(map));        while(m--){            scanf("%d%d",&a,&b);            map[a][b]=map[b][a]=1;        }        for(i=1;i<=n;i++){            for(j=1;j<=n;j++){                if(!map[i][j]&&i!=j){                    addedge(i,j);                }            }        }        memset(vis,0,sizeof(vis));        for(i=1;i<=n;i++){            if(!dfn[i])Tarjan(i,-1);        }        for(i=1;i<=n;i++){            if(!vis[i])ans++;        }        printf("%d\n",ans);    }    return 0;}
?

热点排行