最大权闭合子图
有两种建图方式
下面 表示寿司 的编号
第二种建图其实就是把
考虑一下正确性
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e6+10;
const int inf=1e9;
int n,m,s,t,sumn;
int a[maxn],id[509][509],w[509][509],num,ok[maxn],dis[maxn],idsi[maxn];
struct edge{
int to,nxt,flow;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
d[++cnt]=(edge){v,head[u],flow},head[u]=cnt;
d[++cnt]=(edge){u,head[v],0},head[v]=cnt;
}
bool bfs()
{
for(int i=0;i<=t;i++) dis[i]=0;
dis[s]=1;
queue<int>q; q.push( s );
while( !q.empty() )
{
int u=q.front(); q.pop();
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( d[i].flow&&dis[v]==0 )
{
dis[v]=dis[u]+1;
if( v==t ) return true;
q.push( v );
}
}
}
return false;
}
int dinic(int u,int flow)
{
if( u==t ) return flow;
int res=flow;
for(int i=head[u];i&&res;i=d[i].nxt )
{
int v=d[i].to;
if( dis[v]==dis[u]+1&&d[i].flow)
{
int temp=dinic(v,min(res,d[i].flow) );
if( temp==0 ) dis[v]=0;
res-=temp;
d[i].flow-=temp;
d[i^1].flow+=temp;
}
}
return flow-res;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
cin >> w[i][j];
id[i][j]=++num;
}
for(int i=1;i<=n;i++)//种类
if( !ok[a[i]] ) ok[a[i]]=1,idsi[a[i]]=++num;
s=0,t=num+n+1;
memset(ok,0,sizeof(ok));
for(int i=1;i<=n;i++)//种类向汇点连mx^2
if( !ok[a[i]] ) add(idsi[a[i]],t,m*a[i]*a[i] ),ok[a[i]]=1;
for(int i=1;i<=n;i++)
{
add(num+i,idsi[a[i]],inf);//连向种类
add(num+i,t,a[i] );//连向汇点
}
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
add(id[i][j],num+i,inf);
add(id[i][j],num+j,inf);
/*for(int q=i;q<=j;q++)
add(id[i][j],num+q,inf);*/
if( w[i][j]>0 )
{
sumn+=w[i][j];
add(s,id[i][j],w[i][j] );
}
else
add(id[i][j],t,-w[i][j] );
if( i!=j )
{
add(id[i][j],id[i+1][j],inf);
add(id[i][j],id[i][j-1],inf);
}
}
int ans=0;
while( bfs() ) ans+=dinic(s,inf);
cout << sumn-ans;
}
建图代码(抄的小粉兔代码)
int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i) scanf("%d", &A[i]), MxA = std::max(MxA, A[i]);
DinicFlow::S = 1, DinicFlow::T = 2;
cnt = 2;
for (int i = 1; i <= N; ++i) for (int j = i; j <= N; ++j) {
scanf("%d", &F[i][j]), Id[i][j] = ++cnt;
}
for (int i = 1; i <= N; ++i) for (int j = i; j <= N; ++j) {
int cost = F[i][j];
if (i == j) {
if (M) DinicFlow::insw(Id[i][j], cnt + A[i], Inf);
cost -= A[i];
}
else {
DinicFlow::insw(Id[i][j], Id[i + 1][j], Inf);
DinicFlow::insw(Id[i][j], Id[i][j - 1], Inf);
}
if (cost > 0) DinicFlow::insw(1, Id[i][j], cost), Ans += cost;
if (cost < 0) DinicFlow::insw(Id[i][j], 2, -cost);
}
if (M) for (int i = 1; i <= MxA; ++i) DinicFlow::insw(++cnt, 2, i * i);
DinicFlow::N = cnt;
printf("%lld\n", Ans - DinicFlow::Dinic());
return 0;
}