求最大满意值即求最小舍弃满意度,转化为最小割问题。
假设S集为文科,T集为理科。
从s向每个点i连一条流量为art[i]的边(割掉这条边后i点属于T集合,即选择理科,舍弃文科满意度)
从每个点i向t连一条流量为sci[i]的边(同理)
加点i+n表示对于i及与i相邻点是否都选择文科的决策,i+2*n理科
从s向每个i+n连一条流量为sameart[i]的边,从每个i+n向i和i相邻点连一条流量为inf的边
(看图中下方的图:显然如果存在任意一条sci没有割掉,sameart就要割掉,即这几个人中如果存在任意一人选择理科,就不能满足几个人同时选文科的条件,舍弃sameart)
从每个i+2*n向t连一条流量为samesci[i]的边,从每个i和i相邻点向每个i+2*n连一条流量为inf的边(同理)
#include<cstdio>
int num=1,head[40005],ans,x,t,d[40005],h[40005],n,m;
struct node{int to,next,flow;}e[400005];
void add(int u,int v,int flow)
{
e[++num]=(node){v,head[u],flow},head[u]=num;
e[++num]=(node){u,head[v],0},head[v]=num;
}
int min(int a,int b){return a<b?a:b;}
bool bfs()
{
for(int i=0;i<t;i++)d[i]=0;d[t]=1;
int l=0,r=1;h[1]=t;
while(l!=r)
{
int u=h[++l];
for(int i=head[u];i;i=e[i].next)
if(e[i^1].flow)
{
int v=e[i].to;
if(!d[v])d[v]=d[u]+1,h[++r]=v;
}
}
return d[0];
}
int dfs(int u,int flow)
{
if(u==t)return flow;
int ans=0;bool used=0;
for(int i=head[u];i;i=e[i].next)
if(e[i].flow)
{
int v=e[i].to;if(d[u]!=d[v]+1)continue;
int tmp=dfs(v,min(flow,e[i].flow));
if(tmp)
{
flow-=tmp;e[i].flow-=tmp;
ans+=tmp;e[i^1].flow+=tmp;used=1;
if(!flow)break;
}
}
if(!used)d[u]=-1e9;
return ans;
}
int main()
{
scanf("%d%d",&n,&m);t=(n*m)*3+1;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
scanf("%d",&x),ans+=x,add(0,i*m+j-m,x);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
scanf("%d",&x),ans+=x,add(i*m+j-m,t,x);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
{
scanf("%d",&x);ans+=x;int id=i*m+j-m;
add(0,id+n*m,x),add(id+n*m,id,1e9);
if(i>1)add(id+n*m,id-m,1e9);
if(i<n)add(id+n*m,id+m,1e9);
if(j>1)add(id+n*m,id-1,1e9);
if(j<m)add(id+n*m,id+1,1e9);
}
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
{
scanf("%d",&x);ans+=x;int id=i*m+j-m;
add(id+n*m*2,t,x),add(id,id+n*m*2,1e9);
if(i>1)add(id-m,id+n*m*2,1e9);
if(i<n)add(id+m,id+n*m*2,1e9);
if(j>1)add(id-1,id+n*m*2,1e9);
if(j<m)add(id+1,id+n*m*2,1e9);
}
while(bfs()){int tmp=dfs(0,1e9);if(!tmp)break;ans-=tmp;}
printf("%d\n",ans);
}
一点感想:
一定要弄清楚现在求的到底是什么,是【最小舍弃满意值】而不是【最大满意值】,我们已经装满东西了只要负责扔而不要再去想着怎么装。
像这种同时满足条件的【与】问题,尝试转化成最小割用【或】求解,即把要同时满足的条件代表的点汇集到一个加点上,然后连出一条不满足条件要舍弃的值。
本文介绍如何将文理分科问题转化为最小割问题,通过建立适当的图模型并运用最小割算法求解最大满意值与最小舍弃满意度。
306

被折叠的 条评论
为什么被折叠?



