【LOJ 網絡流24題】最長遞增子序列

最長遞增子序列

題解:

對於第一個查詢直接dpdp即可,dpidp_{i}代表以ii結尾的最長上升子序列的最大長度,計算出ss
對於第二個查詢,對於每個點拆分成兩個點i1,i2i_1,i_2,如果dpidp_i11,則SSi1i_1連接流量爲11的邊,
如果dpidp_iss,則i2i_2TT連接流量爲11的邊,對於每個i2>i1i_2->i_1連接流量爲11的邊,對於滿足i>ji>j並且dpi=dpj+1dp_{i}=dp_{j}+1並且ajaia_{j} \leq a_{i}。則jji+ni+n連接一條流量爲11的邊,跑最大流即可。
對於第三個查詢,只需將SSdpdp值爲11的流量和dpdp值爲ssTT的流量設置爲infinf即可。

代碼:

#include<bits/stdc++.h>

using namespace std;
const int  maxn = 2000;
const int N = 60000;
const int INF = 0x3f3f3f3f;
int S,T,n,m,head[N],dep[N],nxt[N],w[N],num=1,to[N];
bool vis[maxn];
queue<int> q;
void add(int u,int v,int ww){
    num++;
    to[num]=v;nxt[num]=head[u];w[num]=ww;head[u]=num;
    num++;
    to[num]=u;nxt[num]=head[v];w[num]=0;head[v]=num;
}
bool bfs(){
    while(!q.empty()) q.pop();
    memset(vis,0,sizeof(vis));
    dep[S]=0;vis[S]=1;
    q.push(S);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(vis[v]||w[i]<=0) continue;
            vis[v]=1;dep[v]=dep[u]+1;
            q.push(v);
        }
    }
    return vis[T];
}
int dfs(int u,int d){
    if(u==T||d==0) return d;
    int ret=0;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(dep[v]!=dep[u]+1||w[i]<=0) continue;
        int flow=dfs(v,min(d,w[i]));
        d-=flow;ret+=flow;
        w[i]-=flow;w[i^1]+=flow;
        if(d==0) break;
    }
    if(ret==0){
        dep[u]=-1;
    }
    return ret;
}
int a[maxn];
int dp[maxn];
void solve(){
    for(int i=1;i<=n;i++){
        dp[i]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[j]<=a[i]){
                dp[i]=max(dp[i],dp[j]+1);
            }
        }
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    solve();
    int s=0;
    for(int i=1;i<=n;i++) s=max(s,dp[i]);
    cout<<s<<endl;
    if(s==1){
        cout<<n<<endl;
        cout<<n<<endl;
        return 0;
    }
    int ans1,ans2;
    ans1=ans2=0;
    S=0;T=2*n+1;
    for(int i=1;i<=n;++i){
        add(i+n,i,1);
        if(dp[i]==1) add(S,i,1);
        if(dp[i]==s){
             add(i+n,T,1);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(dp[i]+1==dp[j]&&a[i]<=a[j]){
                 add(i,j+n,1);
            }
        }
    }
    while(bfs()) ans1+=dfs(S,INF);
    cout<<ans1<<endl;
    num=1;
    memset(head,0,sizeof(head));
    memset(nxt,0,sizeof(nxt));
    memset(to,0,sizeof(to));
    for(int i=1;i<=n;++i){
        add(i+n,i,1);
        if(dp[i]==1) add(S,i,INF);
        if(dp[i]==s){
             add(i+n,T,INF);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(dp[i]+1==dp[j]&&a[i]<=a[j]){
                 add(i,j+n,1);
            }
        }
    }
    while(bfs()) ans2+=dfs(S,INF);
    cout<<ans2<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章