zoukankan      html  css  js  c++  java
  • POJ2942:Knights of the Round Table——题解

    http://poj.org/problem?id=2942

    所写的tarjan练习题最难的一道。

    说白了难在考得不是纯tarjan。

    首先我们把仇恨关系处理成非仇恨关系的图,然后找双连通分量,在双连通分量里的点满足了任意一个人可以和两个(或以上)的人坐一起。

    那么我们接下来要判断奇环。

    发现性质:如果一个双连通分量有奇环,那么其中任意一点一定在某个奇环上。

    也就是说,这些人拼一拼绝对能全部开会成功,我们把他们打上成功标志。

    然后搜失败标志的人的个数即可。

    判断奇环的方法显然二分图染色。

    #include<stack>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    inline int read(){
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*w;
    }
    const int maxn=1001;
    struct node{
        int st;
        int to;
        int nxt;
    }edge[2000001];
    int cnt,head[maxn];
    void add(int u,int v){
        cnt++;
        edge[cnt].st=u;
        edge[cnt].to=v;
        edge[cnt].nxt=head[u];
        head[u]=cnt;
        return;
    }
    bool dis[maxn][maxn];
    bool ok[maxn];
    int color[maxn];
    int dfn[maxn];
    int low[maxn];
    bool inslt[maxn];
    int t=0;
    int n,m;
    int numslt[maxn];
    stack<int>q;
    vector<int>slt[maxn];
    int slt_cnt;
    void tarjan(int u,int f){
        t++;
        dfn[u]=t;
        low[u]=t;
        for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(!dfn[v]){
            q.push(i);
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
            slt_cnt++;
            slt[slt_cnt].clear();
            while(233){
                int num=q.top();
                q.pop();
                if(numslt[edge[num].st]!=slt_cnt){
                numslt[edge[num].st]=slt_cnt;
                slt[slt_cnt].push_back(edge[num].st);
                }
                if(numslt[edge[num].to]!=slt_cnt){
                numslt[edge[num].to]=slt_cnt;
                slt[slt_cnt].push_back(edge[num].to);
                }
                if(edge[num].to==v&&edge[num].st==u)break;
            }
            }
        }else if(f!=v){
            if(low[u]>dfn[v]){
            q.push(i);
            low[u]=dfn[v];
            }
        }
        }
        return;
    }
    bool draw(int u){
        bool ret=0;
        for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(!inslt[v])continue;
        if(color[v]==-1){
            color[v]=1-color[u];
            ret|=draw(v);
        }else if(color[v]==color[u]){
            return 1;
        }
        }
        return ret;
    }
    void clr(){
        cnt=0;slt_cnt=0;
        while(!q.empty())q.pop();
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(numslt,0,sizeof(numslt));
        memset(head,0,sizeof(head));
        memset(dis,0,sizeof(dis));
        memset(ok,0,sizeof(ok));
        return;
    }
    int main(){
        n=read();
        m=read();
        while(n||m){
        clr();
        for(int i=1;i<=m;i++){
            int u=read();
            int v=read();
            dis[u][v]=dis[v][u]=1;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
            if(!dis[i][j]){
                add(i,j);
                add(j,i);
            }
            }
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
            tarjan(i,0);
            }
        }
        for(int i=1;i<=slt_cnt;i++){
            memset(inslt,0,sizeof(inslt));
            memset(color,-1,sizeof(color));
            int u;
            for(int j=0;j<slt[i].size();j++){
            u=slt[i][j];
            inslt[u]=1;
            }
            color[u]=0;
            if(draw(u)){
            for(int j=0;j<slt[i].size();j++){
                u=slt[i][j];
                ok[u]=1;
            }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)if(!ok[i])ans++;
        printf("%d
    ",ans);
        n=read();m=read();
        }
        return 0;
    }
  • 相关阅读:
    zabbix邮件报警
    简单的带权随机算法
    一、向量
    C#遍历DataSet
    旅游(二)——广州
    旅游(一)——潮州
    LoRa术语
    Linux基础(一)
    Git(二)_基本命令
    Git使用(一)——Cygwin
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7852695.html
Copyright © 2011-2022 走看看