• P4298 [CTSC2008]祭祀


    P4298 [CTSC2008]祭祀

    传递闭包跑一遍按联通建图

    $(1)$最长反链长度=最小链覆盖=n-最大匹配

    $(2)$定义作为最大匹配出现在左端点的集合为$S$,作为最大匹配出现在右端点的集合为$T$

    定义函数$ft(x)$为$S$中任意点在$T$中的对应点,定义函数$fs(s)$为$T$中任意点在$S$中的对应点

    先找最大匹配,从$S$的补集出发增广,当然这里增广不是真正意义上的增广,只是遍历并标记经过的点而已

    左边没有标记过的或右边标记过的就是最小点覆盖,也就是最大独立集的补集

    $(3)$枚举点,每次删掉在跑匹配就行

     My complete code: 

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    struct node{
        int to,next;
    }edge[11000];
    int n,m,ans,link,num,cnt,idx,ci; int dis[210][210],head[210],mat[210],to[210],s[210],t[210],visit[210];
    bool del[210];
    inline void add(int u,int v){
        edge[++cnt]=(node){v,head[u]}; head[u]=cnt;
    }
    bool dfs(int u){
        if(del[u])
            return false;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(visit[v]!=idx&&!del[v]){
                visit[v]=idx;
                if(!mat[v]){
                    to[u]=v;
                    mat[v]=u;
                    return true;
                }else if(dfs(mat[v])){
                    to[u]=v;
                    mat[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    void cal(int u){
        if(s[u])
            return;
        s[u]=1;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(t[v])
                continue;
            t[v]=1;
            cal(mat[v]);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            dis[u][v]=1;
        }
        for(int k=1;k<=n;++k)
            for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j)
                    dis[i][j]|=(dis[i][k]&dis[k][j]);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(dis[i][j])
                    add(i,j);
        ans=n;
        idx=0;
        memset(del,false,sizeof(del));
        for(int i=1;i<=n;++i){
            ++idx;	
            if(dfs(i))
        		ans--;
        }
        printf("%d
    ",ans);
        for(int i=1;i<=n;++i)
            if(!to[i])
                cal(i);
        for(int i=1;i<=n;++i)
            printf("%d",!t[i]&&s[i]);puts("");
        for(int i=1;i<=n;++i){
            memset(del,false,sizeof(del));
            memset(mat,0,sizeof(mat));
            memset(visit,0,sizeof(visit));
            int nn=0;
            for(int j=1;j<=n;++j)
                if(dis[i][j] || j==i || dis[j][i])
                    del[j]=true;
                else
                    nn++;
            idx=0;
            for(int j=1;j<=n;++j)
                if(!del[j]){
        			++idx;
            	    if(dfs(j))
                	    nn--;
                }
            if(nn==ans-1)
                printf("1");
            else
                printf("0");
        }
        return 0;
    }
    

      

  • 相关阅读:
    Android jni/ndk编程五:jni异常处理
    Android jni/ndk编程四:jni引用类型
    Android jni/ndk编程三:native访问java
    Android jni/ndk编程二:jni数据类型转换(primitive,String,array)
    Android jni/ndk编程一:jni初级认识与实战体验
    C++静态库与动态库
    Android——NativeActivity
    Eclipse IDE for C/C++ Developers和MinGW安装配置C/C++开发学习环境详解
    Android OkHttp3简介和使用详解*
    Android MVP 设计模式*
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10121831.html
Copyright © 2020-2023  润新知