LG2766 longest subsequence problem does not fall Network maximum flow network flow 24 questions

Problem Description

LG2766


answer

\(\mathrm{Subtask 1}\)

The problem is not seeking a maximum decrease sequences found \ (n-\ Le 500 \) , direct \ (O (n ^ 2) \) violence to DP.

\(\mathrm{Subtask 2}\)

Set \ (opt_i \) representative of the interval \ ([. 1, I] \) , and to \ (I \) is the end of the longest sequence is not reduced.

Consider split point, the \ (I \) is split into \ (I \) and \ (n-I + \) .

If \ (. 1 opt_i = \) , from the source node to \ (I \) connected edges.

If \ (n-opt_i = \) , from \ (i + n \) to sink even edges.

Collage right above two are \ (INF \) .

Next, from the (I \) \ to \ (i + n \) connected side, the right side of \ (1 \) , representing each number can only be used once.

Next enumeration \ (I, J \) , and \ (I <J \) , \ (\ FORALL a_j \ Le a_i \) and \ (. 1 + opt_i opt_j = \) , in \ (j + n, i \) is connected between the side, the right side is \ (1 \) .

Running \ (\ mathrm {Dinic} \ ) can.

\(\mathrm{Subtask 3}\)

Only need to lift the \ (1 \) and (n \) \ traffic restrictions can be.


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

template <typename Tp>
void read(Tp &x){
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-'){
        fh=-1;ch=getchar();
    }
    else fh=1;
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    x*=fh;
}

const int maxn=507;

int n,a[maxn],len=1;
int opt[maxn],ans;
int S,T;
int Head[20000],v[200000],w[200000],tot=1;
int d[20000],Next[200000];
bool bfs(){
    memset(d,0,sizeof(d));
    queue<int>q;q.push(S);d[S]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=Head[x];i;i=Next[i]){
            if(d[v[i]]||!w[i]) continue;
            q.push(v[i]);d[v[i]]=d[x]+1;
            if(v[i]==T) return true;
        }
    }
    return false;
}

int dfs(int x,int flow){
    if(x==T) return flow;
    int rest=flow;
    for(int i=Head[x];i&&rest;i=Next[i]){
        if(d[v[i]]!=d[x]+1||!w[i]) continue;
        int k=dfs(v[i],min(rest,w[i]));
        if(!k) d[v[i]]=0;
        else{
            w[i]-=k,w[i xor 1]+=k;
            rest-=k;
        }
    }
    return flow-rest;
}

void add(int x,int y,int z){v[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;}

int main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);opt[i]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[i]>=a[j]){
                opt[i]=max(opt[i],opt[j]+1);
                len=max(opt[i],len);
            }
        }
    }
    printf("%d\n",len);S=n*2+1,T=S+1;
    for(int i=1;i<=n;i++){
        if(opt[i]==1) add(S,i,1),add(i,S,0);
    }
    for(int i=1;i<=n;i++){
        if(opt[i]==len) add(i+n,T,1),add(T,i+n,0);
    }
    for(int i=1;i<=n;i++) add(i,i+n,1),add(i+n,i,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[i]>=a[j]&&opt[i]==opt[j]+1){
                add(j+n,i,1);add(i,j+n,0);
            }
        }
    }
    while(bfs()){
        int t;
        while(t=dfs(S,0x3f3f3f3f)) ans+=t;
    }
    printf("%d\n",ans);
    add(1,1+n,0x3f3f3f3f);add(n+1,1,0);
    add(S,1,0x3f3f3f3f);add(1,S,0);
    if(opt[n]==len) add(n,n+n,0x3f3f3f3f),add(2*n,n,0),add(n*2,T,0x3f3f3f3f),add(T,n*2,0);
    while(bfs()){
        ans+=dfs(S,0x3f3f3f3f);
    }
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/liubainian/p/11517222.html