首页 > 其他 > 详细

网络流 24 题 最长递增子序列问题

时间:2020-12-10 21:51:15      阅读:39      评论:0      收藏:0      [点我收藏+]

拆点保证每个点只用一次

#include<bits/stdc++.h>
#define FT(a,b) memset(a,b,sizeof(a))
using namespace std;

const int N = 1000 + 10,M = (N*N + 2*N) << 1,INF = 0x3f3f3f3f;

int e[M],ne[M],w[M],h[N],idx;
int n,m,s,t;
int deepth[N],cur[N],gap[N];
int dp[N],a[N];
void add(int a,int b,int c)
{
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
    swap(a,b),c = 0;
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
    
}

void bfs()
{
    queue<int> q;
    FT(gap,0),FT(deepth,-1);
    q.push(t);
    gap[0] = 1,deepth[t] = 0;
    while(q.size())
    {
        int a = q.front();
        q.pop();
        for(int i = h[a];~i;i = ne[i])
        {
            int j = e[i];
            if(deepth[j] == -1)
            {
                q.push(j);
                deepth[j] = deepth[a] + 1;
                gap[deepth[j]]++;
            }
        }
    }
}
int dfs(int now,int flow)
{
    if(now == t)
        return flow;
    int nowflow = 0;
    for(int i = cur[now];~i;i = ne[i])
    {
        cur[now] = i;
        int j = e[i];
        if(w[i]&&deepth[j] + 1== deepth[now])
        {
            int k = dfs(j,min(flow - nowflow,w[i]));
            nowflow += k,w[i]-=k,w[i^1]+=k;
            if(nowflow == flow)
                return flow;
        }
    }
    --gap[deepth[now]];
    if(!gap[deepth[now]])
        gap[s] = n+2;
    ++deepth[now];
    ++gap[deepth[now]];
    return nowflow;
}
int ISAP()
{
    int ans = 0;
    bfs();
    while(gap[s] < n)
    {
        memcpy(cur,h,sizeof(h));
        ans += dfs(s,INF);
    }
    return ans;
}
int main()
{
    FT(h,-1),idx = 0;
    cin >> n;
    s = 0, t = 2 * n + 1;
    for(int i = 1;i<=n;i++) dp[i] = 1,cin >> a[i];
    int Max = 0;
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j < i;j++)
        {
            if(a[i]>=a[j])
                dp[i] = max(dp[i],dp[j] + 1);
        }
        Max = max(Max,dp[i]);
    }
    cout << Max <<endl;
    if(Max == 1)
    {
        cout << n << \n << n << endl;
    }
    else
    {
        for(int i = 1;i<=n;i++)
        {
            if(dp[i] == 1)
                add(s,i,1);
            if(dp[i] == Max)
                add(i+n,t,1);
            add(i,i+n,1);
            for(int j = 1;j < i;j++)
            {
                if(a[i]>=a[j]&&dp[i] == dp[j] + 1)
                    add(j + n,i,1);
            }
        }
        int ans = ISAP();
        cout << ans << endl;
        for (int i = 0; i < idx; i += 2)
        {
            int a = e[i ^ 1], b = e[i];
            if (a == s && b == 1) w[i] = INF;
            else if (a == 1 && b == n + 1) w[i] = INF;
            else if (a == n && b == n + n) w[i] = INF;
            else if (a == n + n && b == t) w[i] = INF;
        }
        // cout << dp[n] << endl;
        cout << ans + ISAP() << endl;
    }
    return 0;
}

 

网络流 24 题 最长递增子序列问题

原文:https://www.cnblogs.com/ignorance/p/14116533.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!