• bzoj2184: 任意图的匹配


    Description

    每天都要考,每天都要讲,大家注意力都集中不起来了,每天听解题报告时都有人交头接耳(也包括我,呵呵)。这样做大大的影响的学习效率(可能吧)。于是,有些好奇心重的同学就开始研究,怎样才会最吵。培训的总共有N个人,但不是每两人之间都讲话,只有一些人有话题聊,而且一个人可能会和多个人有话题(共M对人)。如果所有同学都说在话,教室里最吵。你的任务就是求出把说话者对数控制在多少人以内,无论如何教室里不会变得最吵?注意:A和B说话,同时B和C说话,这算两对人说话。

    Input

    第一行两个整数N,M。接下来M行,每行两个整数x,y表示x和y有话题聊。

    Output

    一行,一个整数表示要把说话者对数控制在多少以内,无论如何教室里不最吵。

    若有孤立点,则答案为M,否则设最少用k条边覆盖所有点,则答案为k-1

    k=N-最大匹配

    #include<bits/stdc++.h>
    const int N=10007;
    int es[N],enx[N],e0[N],ep,q[N],ql,qr,n,m,f[N],nx[N],pv[N],t[N],ts[N],tk=0,ans=0;
    void ae(int a,int b){
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
    }
    int get(int x){return x!=f[x]?f[x]=get(f[x]):x;}
    int lca(int x,int y){
        ++tk;
        while(1){
            if(x){
                x=get(x);
                if(ts[x]==tk)return x;
                ts[x]=tk;
                x=pv[nx[x]];
            }
            std::swap(x,y);
        }
    }
    void mg(int a,int b){
        while(a!=b){
            int w=nx[a],u=pv[w];
            if(get(u)!=b)pv[u]=w;
            if(t[a]==2)t[q[++qr]=a]=1;
            if(t[w]==2)t[q[++qr]=w]=1;
            if(a==f[a])f[a]=b;
            if(w==f[w])f[w]=b;
            a=u;
        }
    }
    int bfs(int w0){
        for(int i=1;i<=n;++i)f[i]=i,pv[i]=0,t[i]=0;
        ql=qr=0;
        q[++qr]=w0;
        while(ql!=qr){
            int w=q[++ql];
            for(int i=e0[w];i;i=enx[i]){
                int u=es[i];
                if(u==nx[w]||get(w)==get(u)||t[u]==2)continue;
                if(t[u]==1){
                    int v=lca(w,u);
                    if(get(w)!=v)pv[w]=u;
                    if(get(u)!=v)pv[u]=w;
                    mg(w,v);mg(u,v);
                }else if(nx[u]){
                    pv[u]=w;
                    t[u]=2;
                    t[q[++qr]=nx[u]]=1;
                }else{
                    while(w){
                        int a=nx[w];
                        nx[w]=u;nx[u]=w;
                        u=a;
                        w=pv[u];
                    }
                    return 1;
                }
            }
        }
        return 0;
    }
    int main(){
        while(scanf("%d%d",&n,&m)==2){
            memset(e0,0,sizeof(int)*(n+1));
            memset(nx,0,sizeof(int)*(n+1));
            ep=2;
            for(int i=1,a,b;i<=m;++i){
                scanf("%d%d",&a,&b);
                ae(a,b);
            }
            for(int i=1;i<=n;++i)if(!e0[i]){
                printf("%d
    ",m);
                goto o;
            }
            ans=0;
            for(int i=1;i<=n;++i)if(!nx[i])ans+=bfs(i);
            printf("%d
    ",n-ans-1);
            o:;
        }
        return 0;
    }
  • 相关阅读:
    事件的记忆碎片
    委托的记忆碎片
    Jquery的集合方法EACH()
    sql server中的 SET NOCOUNT ON 的含义
    nyist 299 Matrix Power Series
    poj 1061 青蛙约会
    nyist 488 素数环
    nyist 301 递推求值
    nyist 95 众数问题
    nyist 640 Geometric sum
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6307683.html
Copyright © 2020-2023  润新知