Bzoj3894文理分科

注意到所有学生分为文理两科实际是把所有学生分为两个集合,如果相邻点全为同一集合有额外贡献

与最小割模型类似,考虑用最小割来解这道题

所有割到s的集合的点如果相邻点有割到t集合的就要去掉共有贡献,但是不论他周围有多少与他不同的人,这个贡献只会被扣一次,所以考虑拆点

可以观察到如果一个点没有选择文科,那么也必然不会有文科共同贡献,理科亦然,所以考虑把选每科贡献与每科共同贡献统一起来

然后就可以构图了

设a[x]为x选文科满意度,s[x]为选理科满意度

Sa[x],Ss[x]分别为选两科的共同贡献

把每个点拆成三个点ux,x,dx,源向x连容量为a[x]+Sa[x]的边,x向汇连容量为s[x]+Ss[x]的边

x向ux连容量为Sa[x]的边,dx向x连容量为Ss[x]的边

ux向所有与x相邻的点连容量为INF的边,所有与x相邻的点向dx连容量为INF的边

跑最小割即可

代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;

inline int _min(int a,int b) {return a<b?a:b;}

#define MAXN 30005

const int S=MAXN-3,T=MAXN-2;
int n,m,fix,fix2,ans;
struct Edge{
    int from,to,next,v;
}e[MAXN*10];
int cnt=1,head[MAXN];
inline void insert(int a,int b,int f) {
    e[++cnt].next=head[a];head[a]=cnt;e[cnt].v=f;e[cnt].to=b;e[cnt].from=a;
    e[++cnt].next=head[b];head[b]=cnt;e[cnt].v=0;e[cnt].to=a;e[cnt].from=b;
}

int mk[105][105],sz,a[105][105],s[105][105],Sa[105][105],Ss[105][105];
int to[4][2]={1,0,0,1,-1,0,0,-1};

int dis[MAXN],bk[MAXN];queue<int> q;
bool Bfs() {
    memset(dis,0,sizeof(dis));
    dis[T]=1;q.push(T);
    while(!q.empty()) {
        int now=q.front();q.pop();
        for(int i=head[now];i;i=e[i].next)
            if(!dis[e[i].to]&&e[i^1].v>0) {
                dis[e[i].to]=dis[now]+1;
                q.push(e[i].to);
            }
    }
    return dis[S];
}
int Dfs(int v,int a) {
    if(v==T) return a;
    int flow=0,k;
    for(int i=head[v];i;i=e[i].next) {
        if(e[i].v>0&&dis[e[i].to]==dis[v]-1) {
            k=Dfs(e[i].to,_min(a,e[i].v));
            a-=k;flow+=k;e[i].v-=k;e[i^1].v+=k;
            if(a==0) return flow;
        }
    }
    return flow;
}
int MaxFlow() {
    int flow=0,h;
    while(Bfs()) {
        while(h=Dfs(S,INF))
            flow+=h;
    }
    return flow;
}

int main() {
    scanf("%d%d",&n,&m);fix=n*m;fix2=n*m*2;
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) {
        mk[i][j]=++sz;
        scanf("%d",&a[i][j]);
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&s[i][j]);
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&Sa[i][j]);
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&Ss[i][j]);
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) {
        ans+=a[i][j]+s[i][j]+Sa[i][j]+Ss[i][j];
        insert(S,mk[i][j],a[i][j]+Sa[i][j]);
        insert(mk[i][j],T,s[i][j]+Ss[i][j]);
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) {
        insert(mk[i][j],mk[i][j]+fix,Sa[i][j]);
        insert(mk[i][j]+fix2,mk[i][j],Ss[i][j]);
        for(int k=0;k<4;k++) {
            if(!mk[i+to[k][0]][j+to[k][1]]) continue;
            insert(mk[i][j]+fix,mk[i+to[k][0]][j+to[k][1]],INF);
            insert(mk[i+to[k][0]][j+to[k][1]],mk[i][j]+fix2,INF);
        }
    }
    printf("%d\n",ans-MaxFlow());
    return 0;
}
时间: 2024-08-14 04:27:10

Bzoj3894文理分科的相关文章

BZOJ3894: 文理分科

Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到: 1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如 果选择理科,将得到science[i][j]的满意值. 2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻

【BZOJ3894】文理分科(最小割)

[BZOJ3894]文理分科(最小割) 题面 BZOJ Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到: 1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如 果选择理科,将得到science[i][j]的满意值. 2.如

bzoj 3894: 文理分科

Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到: 1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如 果选择理科,将得到science[i][j]的满意值. 2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻

BZOJ 3894: 文理分科 [最小割]

3894: 文理分科 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 674  Solved: 392[Submit][Status][Discuss] Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到

第八回(二)新年晚会艺压群芳 文理分科三人聚首

(二) 第八回 新年晚会艺压群芳 文理分科三人聚首 林二忆起数月前旧事,不禁自己笑了起来.期间小谢数次搭桥牵线,林二虽未言谢,自是感激.以至此后多大的事,皆可担待,不过这也是后话.却说光阴飞逝,不觉林二入学已近一载.书院也例行分科文理,林二,阿四一干人等,均素来喜吟古人诗句,势必凑那文科数.小谢心宽体胖,倒不十分热心这事,文科报名时,林二便也将他名字钩上. 谁知当日暑期补习,这三人便同处一班,阿四不禁感慨道:“莫非古人云,风云际会,机缘巧合,真有这事.”说毕三人便哈哈大笑,往阿清店喝可乐去,是时

第八回 新年晚会艺压群芳 文理分科三人聚首[林大帅作品选]

(一)第八回 新年晚会艺压群芳 文理分科三人聚首 诗曰: 舞袖从容歌不尽 ,顿织梦幻望夕阴, 红粉皆寂何处寻 ,阅尽芳菲更伤心. 话说林二于教室前,与那小谢堂妹相识,谁料那姑娘望了林二一眼,竟莫名一溜烟跑了.小谢叫喊不及,只得双手一拍,一脸不解.忙向林二解释道,“我这阿妹平日里落落大方,今儿着实奇怪.”林二方才和她对眼,魂儿又被勾走了,只是望着莉莉二人拐进初院,不作理会.唯那留声机中,梅姐歌声不绝:“一天想,想到过去但已晚...”日后有好事者,为记这二人相遇,乱掐七律一首.说书人也花好大功夫,在

【BZOJ 3894】 文理分科

3894: 文理分科 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 194 Solved: 122 [Submit][Status][Discuss] Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到

BZOJ_3894_文理分科&amp;&amp;BZOJ_2127_happiness_最小割

BZOJ_3894_文理分科_最小割 Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择 一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式 得到: 1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如 果选择理科,将得到science[i][j]的满意值. 2.如果第i行第J列的同

P4313 文理分科 最小割

$ \color{#0066ff}{ 题目描述 }$ 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行描述,每个格子代表一个同学的座位.每位同学必须从文科和理科中选择一科.同学们在选择科目的时候会获得一个满意值.满意值按如下的方式得到: 如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如果选择理科,将得到science[i][j]的满意值. 如果第i行第J列的同学选择了文科,并且他相邻(