刚学OI萌新求助

P2766 最长不下降子序列问题

rEdWhitE_uMbrElla @ 2019-01-23 22:19:02

RT,,好久没写网络流了。。竟然WA成了54分。。。

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

const int N=501*2,M=N*N*2,INF=~0U>>1;

struct edge {
    edge *next,*op;
    int t,c;
}*to[N],*pre[N],es[M],*sta[N],*x1,*xn;

int n,s,t,ec,ans,mf,arr[N],dp[N],level[N],stp[N];

inline void addedge(int a,int b,int c) {
    es[++ec].next = to[a];
    to[a]=es+ec;
    to[a]->t=b;
    to[a]->c=c;
    if (a==1 && b==n+1) x1 = to[a];
    if (a==n && b==n+n) xn = to[a];
    es[++ec].next = to[b];
    to[b]=es+ec;
    to[b]->t=a;
    to[b]->c=0;
    to[a]->op = to[b];
    to[b]->op = to[a];
}

bool label() {
    int head,tail,i,j;
    stp[head=tail=0]=s;
    memset(level,-1,sizeof(level));
    level[s]=0;
    while (head<=tail) {
        i=stp[head++];
        for (edge *e=to[i]; e; e=e->next) {
            j=e->t;
            if (e->c && level[j]==-1) {
                level[j] = level[i]+1;
                if (j==t)
                    return true;
                stp[++tail] = j;
            }
        }
    }
    return false;
}

void augment() {
    int i,j,delta,stop;
    for (i=s; i<=t; i++)
        pre[i] = to[i];
    stp[stop=1]=s;
    while (stop) {
        i=stp[stop];
        if (i!=t) {
            for (; pre[i]; pre[i]=pre[i]->next)
                if (pre[i]->c && level[i] + 1 == level[j=pre[i]->t])
                    break;
            if (pre[i]) {
                stp[++stop] = j;
                sta[stop] = pre[i];
            } else
                stop--,level[i]=-1;
        } else {
            delta = INF;
            for (i=stop; i>=2; i--)
                if (sta[i]->c < delta)
                    delta = sta[i]->c;
            mf += delta;
            for (i=stop; i>=2; i--) {
                sta[i]->c -= delta;
                sta[i]->op->c += delta;
                if (sta[i]->c==0)
                    stop = i-1;
            }
        }
    }
}

void dinic() {
    while (label())
        augment();
}

int main() {
    scanf("%d",&n);
    s=0;
    t=n+n+1;
    for (int i=1; i<=n; i++)
        scanf("%d",&arr[i]);
    for (int i=n; i>=1; i--) {
        dp[i] = 1;
        for (int j=i+1; j<=n; j++)
            if (arr[j] > arr[i] && dp[j]+1 > dp[i])
                dp[i] = dp[j]+1;
        if (dp[i] > ans)
            ans = dp[i];
    }
    printf("%d\n",ans);
    int c,d;
    for (int i=1; i<=n; i++) {
        addedge(i,i+n,1);
        c=d=1;
        if (i==1) c=INF;
        if (i==n) d=INF;
        if (dp[i]==ans)
            addedge(s,i,c);
        if (dp[i]==1)
            addedge(i+n,t,d);
        for (int j=i+1; j<=n; j++)
            if (dp[i] == dp[j]+1)
                addedge(i+n,j,1);
    }
    dinic();
    printf("%d\n",mf);
    x1->c = xn->c = INF;
    dinic();
    printf("%d\n",mf);
    return 0;
}

那个链式前向星链表写的,其实和普通的一样。


by 缥缈的鸿影 @ 2019-01-23 22:31:41

@SLF_LLL_SPFA 刚学OI还很久没写网络流…………?那我怕不是废了


by Aéro_Dynamik @ 2019-02-20 17:34:53

大佬又在装弱%%%


|