• DAG最小可重路径覆盖or最长反链的一种做法


    zrO xtx Orz

    感觉就是抄了一遍https://zybuluo.com/AntiLeaf/note/804022
    不得不说,这个做法非常强。
    由于博主水平有限,有可能有一些纯感性理解的东西.

    首先,最长反链这个说法似乎有一些问题,这里的反链是指互不包含的点集。
    最小可重路径覆盖指边和点都可以重复.
    最小不可重路径覆盖指点不重复.

    这样根据dilworth定理,这个东西对应最小链剖分,也就是求出传递闭包并连边后的DAG的最小不可重路径覆盖。

    最小不可重路径覆盖还是比较简单的.
    他有一个经典做法,拆点建二分图,原点向左边的点连边,容量为1,左边的点向右边的点连原图的边,容量为1,右边的点向汇点连边,容量为1.
    考虑一个匹配的含义就是原来的(n)个路径中的两个结合了.
    那么答案就是点数减最大匹配数.

    最小可重路径覆盖,第一种做法是求出传递闭包,然后转化为不可重,但是点数较多时并不能求出传递闭包.
    另一种做法考虑优化建图,原来的边的含义是直接或间接到达,现在的边只有直接到达的含义,那么为了可以让间接到达存在,每个点的入点向出点连Inf边,并且原图的边连Inf.

    如果这个问题的最长反链是一个点集的呢?
    只需要源点只向该点集连边,只有该点集向汇点连边即可,因为考虑其他的边和点都是维护是否可达关系的辅助边和点.

    一个用到这个的题的代码

    #include <bits/stdc++.h>
      
    using namespace std;
    const int N=100005;
    char ss[N];
    int fa[N];
    int len[N];
    int trans[N][26],la,tot=1;
    int s,t;
    int aa[N];
    int val[N];
    int getfail(char *s,int x,int r){
        while (s[r]!=s[r-len[x]-1]){
            x=fa[x];
            //cerr<<x<<" "<<len[x]<<endl;
        }
        return x;
    }
      
    void init(){
        len[0]=0;
        len[1]=-1;
        fa[0]=1;
    }
      
    void build(char *s,int l,int r){
        //cerr<<"BBBB"<<" "<<la<<endl;
        char c=s[r]-'a';
        int cur=getfail(s,la,r);
        //cerr<<"cur"<<cur<<endl;
        if (!trans[cur][c]){
            ++tot;
            len[tot]=len[cur]+2;
            fa[tot]=trans[getfail(s,fa[cur],r)][c];
            //cerr<<"tot"<<tot<<" "<<fa[tot]<<" "<<cur<<endl;
            trans[cur][c]=tot;
        }
        la=trans[cur][c];
        val[la]=max(val[la],aa[r]);
        //cerr<<"build"<<l<<" "<<r<<endl;
    }
      
    struct edge{
        int y,cap,op;
    };
    int pp=0;
    vector<edge> g[N+N];
    void add(int x,int y,int z){
        //cerr<<"add"<<x<<" "<<y<<" "<<z<<" "<<++pp<<endl;
        g[x].push_back({y,z,g[y].size()});
        g[y].push_back({x,0,g[x].size()-1});
    }
      
    int cur[N+N],d[N+N];
    bool bfs(){
        queue<int> q;
        q.push(s);
        for (int i=s; i<=t; ++i) cur[i]=d[i]=0;
        d[s]=233;
        while (!q.empty()){
            int x=q.front(); q.pop();
            //cerr<<"XXXXXXXXXXXX"<<x<<" "<<g[x].size()<<endl;
            for (auto j:g[x]){
                //cerr<<"cap"<<j.cap<<endl;
                if (j.cap&&!d[j.y]){
                    //cerr<<j.y<<endl;
                    d[j.y]=d[x]+1;
                    q.push(j.y);
                }
            }
        }
        //cerr<<d[t]<<endl;
        return d[t];
    }
      
    int dfs(int x,int fl){
        if (x==t) return fl;
        //cerr<<"dfs"<<x<<" "<<fl<<endl;
        int orz=fl;
        for (int &j=cur[x]; j<g[x].size(); ++j){
            edge &e=g[x][j];
            int t=0;
            if (e.cap&&d[e.y]==d[x]+1&&(t=dfs(e.y,min(fl,e.cap)))){
                //cerr<<"init"<<endl;
                e.cap-=t;
                g[e.y][e.op].cap+=t;
                fl-=t;
                if (!fl) return orz;
            }
        }
        return orz-fl;
    }
    int maxflow(){
        int ans=0;
        while (bfs()){
            //cerr<<"BFS"<<endl;
            //for (int i=s; i<=t; ++i) cerr<<d[i]<<" ";
            //cerr<<endl;
            //getchar();
            ans+=dfs(s,2333333);
        }
        //cerr<<"ans"<<ans<<endl;
        return ans;
    }
      
      
    int calc(int lim){
        //cerr<<"calc"<<lim<<endl;
        s=0;
        t=tot*2+1;
        int bbbb=0;
        for (int i=s; i<=t; ++i) g[i].clear();
        for (int i=2; i<=tot; ++i){
            //cerr<<"IIIII"<<i<<endl;
            if (val[i]>=lim){
                ++bbbb;
                add(s,i*2-1,1);
                add(i*2,t,1);
            }
            add(i*2,i*2-1,23333333);
        }
        //cerr<<"___________"<<endl;
        //cerr<<"tot"<<tot<<endl;
        for (int i=2; i<=tot; ++i)
            for (int c=0; c<26; ++c){
            if (trans[i][c]){
                add(i*2-1,trans[i][c]*2,233333);
            }
        }
        for (int i=2; i<=tot; ++i)
            if (fa[i]>1) add(fa[i]*2-1,i*2,2333333);
      
      
          
        return bbbb-maxflow();
    }
      
    void update(){
        for (int i=tot; i>=2; --i) val[fa[i]]=max(val[fa[i]],val[i]);
    }
      
    int n,k;
    int main(){
        scanf("%d%d",&n,&k);
        scanf("%s",ss+1);
        vector<int> v;
        for (int i=1; i<=n; ++i) scanf("%d",&aa[i]),v.push_back(aa[i]);
        //cerr<<"!!!!!"<<endl;
        init();
        for (int i=1; i<=n; ++i) build(ss,1,i);
        //  for (int i=1; i<=tot; ++i) cerr<<val[i]<<" ";
        update();
        //cerr<<"????"<<endl;
        //cerr<<"tpt:"<<tot<<endl;
        sort(v.begin(),v.end());
        //for (int i=1; i<=tot; ++i) cerr<<fa[i]<<" ";
        //cerr<<endl;
        //for (int i=1; i<=tot; ++i) cerr<<val[i]<<" ";
        //calc(3);
        //return 0;
        int ret=-1;
        for (int l=0,r=v.size()-1,mid=(l+r)>>1; l<=r; mid=(l+r)>>1)
            if (calc(v[mid])>=k) ret=v[mid],l=mid+1; else r=mid-1;
        if (ret==-1) cout<<"NEGATIVE"<<endl;
        else cout<<ret<<endl;
    }
    
  • 相关阅读:
    【版本控制工具】 Git进阶1
    【版本控制工具】 Git基础
    问题:com.alibaba.dubbo.rpc.RpcException: Failed to invoke ......
    互联网安全架构之常见的Web攻击手段及解决办法
    【Spring Boot】七、整合actuator实现监控管理
    问题:tomcat启动后,可以访问主页面,但是无法访问dubbo-admin
    【Spring Boot】六、整合dubbo(注解的方式)
    这篇文章,彻底搞懂八大开源框架源码
    Spring Cloud Greenwich.SR4 发布了,跟不上了……
    手把手教你画架构图,看一次就会了!
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/10634821.html
Copyright © 2020-2023  润新知