• bzoj2127: happiness


    最小割。加点然后sm-maxflow就好了。做过类型题

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define clr(x,c) memset(x,c,sizeof(x))
    int read(){
    	int x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return x;
    } 
    const int nmax=6e4+5;
    const int maxn=4e5+5;
    const int inf=0x7f7f7f7f;
    struct edge{
    	int to,cap;edge *next,*rev;
    };
    edge es[maxn],*pt=es,*head[nmax];
    void add(int u,int v,int d){
    	pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
    	pt->to=u;pt->cap=0;pt->next=head[v];head[v]=pt++;
    	head[u]->rev=head[v];head[v]->rev=head[u];
    }
    edge *p[nmax],*cur[nmax];
    int h[nmax],cnt[nmax],id[105][105];
    int maxflow(int s,int t,int n){
    	cnt[0]=n;int x=s,flow=0,a=inf;edge *e;
    	while(h[s]<n){
    		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]+1==h[x]) break;
    		if(e){
    			a=min(a,e->cap);cur[x]=p[e->to]=e;x=e->to;
    			if(x==t){
    				while(x!=s) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to;
    				flow+=a,a=inf;
    			}
    		}else{
    			if(!--cnt[h[x]]) break;
    			h[x]=n;
    			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e;
    			cnt[h[x]]++;
    			if(x!=s) x=p[x]->rev->to;
    		}
    	}
    	return flow;
    }
    int main(){
    	int n=read(),m=read(),s=0,t=1,cnt=1,tmp,sm=0;
    	rep(i,1,n) rep(j,1,m) id[i][j]=++cnt;
    	rep(i,1,n) rep(j,1,m) add(s,id[i][j],tmp=read()),sm+=tmp;
    	rep(i,1,n) rep(j,1,m) add(id[i][j],t,tmp=read()),sm+=tmp;
    	rep(i,1,n-1) rep(j,1,m) add(s,++cnt,tmp=read()),add(cnt,id[i][j],inf),add(cnt,id[i+1][j],inf),sm+=tmp;
    	rep(i,1,n-1) rep(j,1,m) add(++cnt,t,tmp=read()),add(id[i][j],cnt,inf),add(id[i+1][j],cnt,inf),sm+=tmp;
    	rep(i,1,n) rep(j,1,m-1) add(s,++cnt,tmp=read()),add(cnt,id[i][j],inf),add(cnt,id[i][j+1],inf),sm+=tmp;
    	rep(i,1,n) rep(j,1,m-1) add(++cnt,t,tmp=read()),add(id[i][j],cnt,inf),add(id[i][j+1],cnt,inf),sm+=tmp;
    	printf("%d
    ",sm-maxflow(s,t,cnt+1));
    	return 0;
    }
    /*
    1 2
    1 1
    100 110
    1
    1000 
    */
    

      

    2127: happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 1681  Solved: 820
    [Submit][Status][Discuss]

    Description

    高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

    Input

    第一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

    Output

    输出一个整数,表示喜悦值总和的最大值

    Sample Input

    1 2
    1 1
    100 110
    1
    1000

    Sample Output

    1210
    【样例说明】
    两人都选理,则获得100+110+1000的喜悦值。
    【数据规模】
    对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

    HINT

     

    Source

  • 相关阅读:
    怎样才是全能的程序员?
    [HDU 2553]N皇后问题
    [HDU 1870]愚人节的礼物
    [HDU 1016]Prime Ring Problem
    [HDU 1241]Oil Deposits
    [POJ 3250]Bad Hair Day
    [HDU 1276]士兵队列训练问题
    [POJ 2796]Feel Good
    [HDU 1237] 简单计算器
    总算开通博客园啦~
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5927261.html
Copyright © 2020-2023  润新知