zoukankan      html  css  js  c++  java
  • FZU2181+poj2942(点双连通+判奇圈)

    分析:我们对于那些相互不憎恨的人连边,将每次参加会议的所有人(不一定是全部人,只需人数>=3且为奇数)看做一个点双联通分量,那么每个点都至少有两个点与他相邻。即需要保证双联通分量中存在奇圈。至于如何判奇圈,这里有一个性质:一个图是二分图当且仅当图中不存在奇圈。至于如何判断一个图是否是二分图,可以采用交替染色的方式判断。

    传送门:FZU 2181 快来买肉松饼

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    using namespace std;
    #define MAXN 1005
    
    struct Edge{
        int v,next;
    }edge[MAXN*MAXN*2];
    
    int n,m,NE,ans;
    int head[MAXN];
    bool hate[MAXN][MAXN];
    void Insert(int u,int v)
    {
        NE++;
        edge[NE].v=v;
        edge[NE].next=head[u];
        head[u]=NE;
    }
    
    void Build()
    {
        int a,b;
        memset(hate,false,sizeof(hate));
        while(m--){
            scanf("%d%d",&a,&b);
            hate[a][b]=hate[b][a]=true;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(!hate[i][j]){
                    Insert(i,j);
                    Insert(j,i);
                }
            }
        }
    }
    
    int cnt,_count;
    int low[MAXN],dfn[MAXN];
    int block[MAXN];
    int color[MAXN];
    bool mark[MAXN];
    int num[MAXN];
    bool is_expelled[MAXN];
    stack<int>S;
    bool Judge(int u,int state)
    {
        color[u]=state;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(block[v]==_count){
                if(color[v]&&color[u]==color[v])
                    return true;
                if(!color[v]&&Judge(v,3-state))
                    return true;
            }
        }
        return false;
    }
    void Tarjan(int u,int father)
    {
        int flag=0;
        low[u]=dfn[u]=++cnt;
        mark[u]=true;
        S.push(u);
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(v==father&&!flag){ flag=1;continue; }
            if(dfn[v]==0){
                Tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>=dfn[u]){
                    int x,tmp=0;
                    _count++;
                    do{
                        x=S.top();
                        S.pop();
                        mark[x]=false;
                        block[x]=_count;
                        num[tmp++]=x;
                    }while(x!=v);//割点u可能属于多个连通块,因此不能出栈
                    num[tmp++]=u;
                    memset(color,0,sizeof(color));
                    if(tmp>=3&&Judge(u,1)){
                        while(tmp>0){
                            is_expelled[num[--tmp]]=false;
                        }
                    }
                }
            }else if(mark[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    void init()
    {
        cnt=_count=0;NE=0;
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(block,0,sizeof(block));
        memset(is_expelled,true,sizeof(is_expelled));
        memset(mark,false,sizeof(mark));
    }
    int main()
    {
        int T,k;
        scanf("%d",&T);
        while(T--){
           // if(n==0&&m==0)break;
            scanf("%d%d%d",&n,&m,&k);
            init();
            Build();
            for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i,-1);
            ans=0;
            for(int i=1;i<=n;i++)if(!is_expelled[i])ans++;
            if(ans>=k)puts("Let's Fire!");
            else puts("What a Pity.");
            //printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    传送门:poj 2942 Knights of the Round Table

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    using namespace std;
    #define MAXN 1005
    
    struct Edge{
        int v,next;
    }edge[MAXN*MAXN*2];
    
    int n,m,NE,ans;
    int head[MAXN];
    bool hate[MAXN][MAXN];
    void Insert(int u,int v)
    {
        NE++;
        edge[NE].v=v;
        edge[NE].next=head[u];
        head[u]=NE;
    }
    
    void Build()
    {
        int a,b;
        memset(hate,false,sizeof(hate));
        while(m--){
            scanf("%d%d",&a,&b);
            hate[a][b]=hate[b][a]=true;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(!hate[i][j]){
                    Insert(i,j);
                    Insert(j,i);
                }
            }
        }
    }
    
    int cnt,_count;
    int low[MAXN],dfn[MAXN];
    int block[MAXN];
    int color[MAXN];
    bool mark[MAXN];
    int num[MAXN];
    bool is_expelled[MAXN];
    stack<int>S;
    bool Judge(int u,int state)
    {
        color[u]=state;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(block[v]==_count){
                if(color[v]&&color[u]==color[v])
                    return true;
                if(!color[v]&&Judge(v,3-state))
                    return true;
            }
        }
        return false;
    }
    void Tarjan(int u,int father)
    {
        int flag=0;
        low[u]=dfn[u]=++cnt;
        mark[u]=true;
        S.push(u);
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(v==father&&!flag){ flag=1;continue; }
            if(dfn[v]==0){
                Tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>=dfn[u]){
                    int x,tmp=0;
                    _count++;
                    do{
                        x=S.top();
                        S.pop();
                        mark[x]=false;
                        block[x]=_count;
                        num[tmp++]=x;
                    }while(x!=v);//割点u可能属于多个连通块,因此不能出栈
                    num[tmp++]=u;
                    memset(color,0,sizeof(color));
                    if(tmp>=3&&Judge(u,1)){
                        while(tmp>0){
                            is_expelled[num[--tmp]]=false;
                        }
                    }
                }
            }else if(mark[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    void init()
    {
        cnt=_count=0;NE=0;
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(block,0,sizeof(block));
        memset(is_expelled,true,sizeof(is_expelled));
        memset(mark,false,sizeof(mark));
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)>0){
            if(n==0&&m==0)break;
            init();
            Build();
            for(int i=1;i<=n;i++)if(dfn[i]==0)Tarjan(i,-1);
            ans=0;
            for(int i=1;i<=n;i++)if(is_expelled[i])ans++;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HDU-3065-病毒侵袭持续中(AC自动机)
    HDU-2896-病毒侵袭(AC自动机)
    HDU
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) D. Sequence Sorting
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) B. Strings Equalization
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature
    Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) A. CME
    Codeforces Round #586 (Div. 1 + Div. 2) E. Tourism
    Codeforces Round #586 (Div. 1 + Div. 2) D. Alex and Julian
    jsp内置对象
  • 原文地址:https://www.cnblogs.com/lienus/p/4289390.html
Copyright © 2011-2022 走看看