[六省联考2017]寿司餐厅

题链

这道题长着网络流的数据范围。

最大权闭合子图问题

跑最小割

#include<bits/stdc++.h>
#define eho(x) for(int& i=hed[x];~i;i=net[i])
#define Eho(x) for(int i=head[x];~i;i=net[i])
#define N 52607
#define M 3500007
#define NN 1007
#define sight(c) (c<='9'&&c>='0')
#define INF (1<<29)
using namespace std;
template <class T>
inline void read(T &x) {
    static char c; static int b;
    for(c=getchar(),b=1;!sight(c);c=getchar())if (c=='-') b=-1;
    for(x=0; sight(c); c=getchar()) x=(x<<3)+(x<<1)+c-48; x*=b;
}
struct G {
    int head[N],net[M],fall[M],cost[M],s,t,tot,d[N],hed[N],cost2[M];
    bool in[N];
    queue<int> Q;
    G() {}
    inline void updata() {
        memcpy(cost,cost2,sizeof cost); 
    }
    inline void cpy() {
        memcpy(cost2,cost,sizeof cost);
    }
    inline void clear() {
        memset(head,-1,sizeof head); memset(net,-1,sizeof net); tot=-1;}
    inline void add(int x,int y,int c) {
        fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=c;}
    inline void adds(int x,int y,int c) {
        add(x,y,c); add(y,x,0);}
    inline bool spfa() {
        memset(d,127,sizeof d);
        int x; d[s]=1; Q.push(s); in[s]=1;
        while (!Q.empty()) {
            x=Q.front(); Q.pop();
            Eho(x)
            if (cost[i]&&d[fall[i]]>d[x]+1) {
                d[fall[i]]=d[x]+1;
                if (!in[fall[i]]) {
                    in[fall[i]]=1,Q.push(fall[i]);}
            }
            in[x]=0;
        }
        return d[t]<INF;
    }
    inline int dfs(int x,int F) {
        if (x==t|| !F) return F;
        int flow=0,r;
        eho(x)
        if (d[x]+1==d[fall[i]]&&((r=dfs(fall[i],min(F,cost[i])))>0)) {
            cost[i]-=r; cost[i^1]+=r;
            F-=r; flow+=r;
            if (!F) break;
        }
        return flow;
    }
    int dinic(int A,int B) {
        s=A; t=B;
        int flow=0;
        while (spfa()) {
            memcpy(hed,head,sizeof head);
            flow+=dfs(s,INF);
        }
        return flow;
    }
} G;
int n,m,a[NN],cost[NN][NN],id[NN][NN],vis[NN],idw[NN],cnt,S,T;
long long sum;
int main () {
    G.clear();
    freopen("sushi.in","r",stdin);
    freopen("sushi.out","w",stdout);
    read(n); read(m);
    for (int i=1;i<=n;i++) read(a[i]);
    for (int i=1;i<=n;i++)
     for (int j=i;j<=n;j++) read(cost[i][j]);
    for (int i=1;i<=n;i++)
     for (int j=i;j<=n;j++) id[i][j]=++cnt;
    for (int i=1;i<=n;i++) if (!vis[a[i]]) {
        vis[a[i]]=1; idw[a[i]]=++cnt;
    } T=cnt+n+1; memset(vis,0,sizeof vis);
    for (int i=1;i<=n;i++) if (!vis[a[i]]) {
        vis[a[i]]=1; G.adds(idw[a[i]],T,m*a[i]*a[i]);
    }
    for (int i=1;i<=n;i++) {
        G.adds(cnt+i,idw[a[i]],INF);
        G.adds(cnt+i,T,a[i]);
    }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++){
            if(cost[i][j]>0){
                sum+=cost[i][j];
                G.adds(S,id[i][j],cost[i][j]);
                G.adds(id[i][j],cnt+i,INF);
                G.adds(id[i][j],cnt+j,INF);
            }
            else if(cost[i][j]<0){
                G.adds(id[i][j],T,-cost[i][j]);
                G.adds(id[i][j],cnt+i,INF);
                G.adds(id[i][j],cnt+j,INF);
            }
            if(i^j){
                G.adds(id[i][j],id[i+1][j],INF);
                G.adds(id[i][j],id[i][j-1],INF);
            }
        }
    printf("%lld\n",sum-G.dinic(S,T));
    return 0;
}

 

posted @ 2018-02-27 20:50  泪寒之雪  阅读(226)  评论(0编辑  收藏  举报