【六省2017】寿司餐厅

我发现我学的最大权闭合子图一直是假的,自闭了。

最大权闭合子图:选一点之前一定要选这个点的后继

$S$连正,负连$T$,边权为点权的绝对值。

题面

https://loj.ac/problem/2146

题解

注意离散化之后的二分答案,$n$应该是压缩后的$n$,即$tot$。

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10050
#define INF 1000000007
#define S 0
#define T (cc+1)
#define LL long long
#define ri register int
using namespace std;

int n,m,tot,cc;
int a[145],d[145][145],dct[145];
int bh[145][145];
bool vis[145];

inline int read() {
  int ret=0,f=0; char ch=getchar();
  while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
  while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar();
  return f?-ret:ret;
}

struct graph {
  vector<int> ed[N],w,to;
  int d[N],cur[N],p[N];
  void add_edge(int u,int v,int tw) {
    to.push_back(v); w.push_back(tw); ed[u].push_back(to.size()-1);
    to.push_back(u); w.push_back(0);  ed[v].push_back(to.size()-1);
  }
  bool bfs() {
    queue<int> q;
    memset(d,0x3f,sizeof(d));
    d[S]=0; q.push(S);
    while (!q.empty()) {
      int x=q.front(); q.pop();
      for (ri i=0;i<ed[x].size();i++) {
        int e=ed[x][i];
        if (d[x]+1<d[to[e]] && w[e]) {
          d[to[e]]=d[x]+1;
          q.push(to[e]);
        }
      }
    }
    return d[T]<INF;
  }
  int dfs(int x,int limit) {
    if (x==T || limit==0) return limit;
    int sum=0; 
    for (ri &i=cur[x];i<ed[x].size();i++) {
      int e=ed[x][i];
      if (w[e] && d[x]+1==d[to[e]]) {
        int f=dfs(to[e],min(limit,w[e]));
        if (!f) continue;
        sum+=f; limit-=f; 
        w[e]-=f; w[1^e]+=f;
        if (!limit) return sum;
      }
    }
    return sum;
  }
  int dinic() {
    int ret=0;
    while (bfs()) {
      memset(cur,0,sizeof(cur));
      ret+=dfs(S,INF);
    }
    return ret;
  }
} G;

int main() {
  n=read(); m=read();
  for (ri i=1;i<=n;i++) a[i]=read();
  int sum=0;
  for (ri i=1;i<=n;i++) {
    for (ri j=i;j<=n;j++) {
      d[i][j]=read();
      if (d[i][j]>0) sum+=d[i][j];
    }
  }
  for (ri i=1;i<=n;i++) dct[i]=a[i];
  sort(dct+1,dct+n+1);
  tot=unique(dct+1,dct+n+1)-dct-1;
  cc=tot;
  for (ri i=1;i<=n;i++) bh[i][i]=++cc;
  for (ri i=1;i<n;i++)
    for (ri j=i+1;j<=n;j++) bh[i][j]=++cc;
  for (ri i=1;i<=n;i++) {
    int x=lower_bound(dct+1,dct+tot+1,a[i])-dct;
    if (!vis[x]) {
      vis[x]=1;
      if (m) G.add_edge(x,T,a[i]*a[i]);
    }
    G.add_edge(bh[i][i],T,a[i]);
    G.add_edge(bh[i][i],x,INF);
  }
  for (ri i=1;i<=n;i++) 
    for (ri j=i;j<=n;j++) if (d[i][j]>0) G.add_edge(S,bh[i][j],d[i][j]); else G.add_edge(bh[i][j],T,-d[i][j]);
  for (ri i=1;i<n;i++)
    for (ri j=i+1;j<=n;j++) {
      G.add_edge(bh[i][j],bh[i+1][j],INF);
      G.add_edge(bh[i][j],bh[i][j-1],INF);
    }
  cout<<sum-G.dinic()<<endl;
}

 

posted @ 2019-08-02 20:58  HellPix  阅读(143)  评论(0编辑  收藏  举报