zoukankan      html  css  js  c++  java
  • [CTSC2008]祭祀

    [CTSC2008]祭祀

    0x01 题意

    给出一个DAG,求出这个图的最长反链,并构造方案,以及在反链最长情况下每个点是否能选(有spj)

    0x02 解

    最长反链:一张有向无环图的最长反链为一个集合(Ssubseteq V),满足对于(S)中的任意两个不同的点(u,vin S\,(u eq v))(u)不能到达(v)(v)也不能到达(u),且(S)的大小尽量大。

    第一问:这里有一波二分图整理,记住就行,最长反链=最小链覆盖,而最小链覆盖和最小路径覆盖可以通过传递闭包进行互化,所以反链长度很好求

    第二问:

    结论1:求传递闭包拆点后二分图的最大匹配,从二分图的左部分的非匹配点开始DFS,左边的点只能走非匹配边向右边访问,右边的点只能走匹配边向左边访问,取左边没DFS到的点以及右边DFS到的点组成一个集合,该集合是二分图的一个最小点覆盖

    结论2:求二分图的最大独立集(最小点覆盖的补集),取对应在二分图里的两个点都在最大独立集里的岔口组成一个集合,该集合为一个最长反链方案

    无力证明,小粉兔

    第三问:

    考虑减法原理,删去一个点集对答案的影响,若该点可以选,则删去该点对答案的影响是减一,若该点不能选,对答案的影响是减去一个大于一的数,因为反链中的点互相不能到达,不能作反链点的点一定可以到达反链中的至少两个点

    0x03 码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,N=110,M=1010;
    
    int mapp[N][N],n,m,lx[N];
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    void cdbb(){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    mapp[j][k]|=mapp[j][i]&mapp[i][k];
    }
    
    int match[N],isdel[N],flg[2][N],res;
    bool st[N];
    
    bool find(int x){
    	for(int i=1;i<=n;i++){
    		if(mapp[x][i]==0||isdel[i]) continue;
            if(!st[i]){
    			st[i]=true;
                if(match[i]==0||find(match[i])){
    				match[i]=x;
                    return true;
                }
            }
        }
        
        return false;
    }
    
    int work(){
        int res=0;
        for(int i=1;i<=n;i++){
            memset(st,false,sizeof st);
            if(find(i)) res++;
        }
        return res;
    }
    
    void dfs(int x){
        flg[1][x]=1;
        for(int i=1;i<=n;i++) if(mapp[x][i]&&match[i]!=x&&!flg[0][i]){
            flg[0][i]=1;
            if(match[i]!=0) dfs(match[i]);
        }
    }
    
    void gz(){
        for(int i=1;i<=n;i++) lx[match[i]]=1;
        for(int i=1;i<=n;i++) if(!lx[i]) dfs(i);
        for(int i=1;i<=n;i++) if(!flg[1][i]||flg[0][i]) putchar('0');else putchar('1');
    
        putchar('
    ');
        for(int rt=1;rt<=n;rt++){
            memset(isdel,0,sizeof isdel);
            memset(match,0,sizeof match);
            int cnt=0,nn=n;
            for(int i=1;i<=n;i++) if(mapp[i][rt]||mapp[rt][i]||i==rt) isdel[i]=1,--nn;
            for(int i=1;i<=n;i++){
                if(isdel[i]) continue;
                memset(st,0,sizeof st);
                if(find(i)) ++cnt;
            }
            printf("%d",(nn-cnt==(n-res)-1));
        }
    }
    
    int main(){
        
        memset(mapp,0,sizeof(mapp));
        n=read(),m=read();
        for(int i=1;i<=m;i++){
            int x,y;
            x=read(),y=read();
            mapp[x][y]=1;
        }
        cdbb();
    
        res=work();
        cout<<n-res<<endl;
    
    
        gz();
    
    
        return 0;
    }
    
  • 相关阅读:
    第三十章 混合线程同步构造
    第二十九章 基元线程同步构造
    第二十八章 I/O限制的异步操作
    第二十七章 计算限制的异步操作
    第二十六章 线程基础
    第二十五章 与WinRT组件互操作
    css实现排序箭头
    js中的toFixed神坑
    react使用中碰到的小问题
    看到一个js中sleep的例子,挺好玩的
  • 原文地址:https://www.cnblogs.com/wsyunine/p/14732669.html
Copyright © 2011-2022 走看看