zoukankan      html  css  js  c++  java
  • Luogu P1646 [国家集训队]happiness

    在二元关系中,去除一个割,剩下的部分还是一个割。

    所以这道题我们可以转化为 总权值 - 最小割 来解决最大化的问题。

    具体地,我们设 (A_x) 表示 (x) 选文科的贡献,设 (B_x) 表示 (x) 选理科的贡献,(A_{x,y}) 表示同时选文科的贡献,(B_{x,y}) 表示同时选理科的贡献;并且设割哪条边代表不选哪一科

    总权值:(a+b+c+d+e+f=A_x+B_x+A_y+B_y+A_{x,y}+B_{x,y})

    同时选理:(a+b=A_x+A_y+A_{x,y} (1))

    同时选文:(c+d= B_x+B_y+B_{x,y} (2))

    (x) 选文,(y) 选理:(b+c+e= B_x+A_y+A_{x,y}+B_{x,y} (3))

    (x) 选理,(y) 选文:(a+d+f= A_x+B_y+A_{x,y}+B_{x,y} (4))

    ((3)+(4)-(1)-(2)) 得:

    (e+f=A_{x,y}+B_{x,y}),我们令 (e=f=frac{A_{x,y}+B_{x,y}}{2})

    我们令 (a=A_x+frac{A_{x,y}}{2}),则有:

    (b=A_y+frac{A_{x,y}}{2},c=B_x+frac{B_{x,y}}{2},d=B_y+frac{B_{x,y}}{2})

    在实际运算过程中,我们可以把边权 ( imes 2) 避免浮点数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int L=105,N=10010,M=200010,Inf=0x3f3f3f3f;
    int n,m,cnt=1,ans,s,t,a[L][L],b[L][L];
    int vr[M],nxt[M],w[M],fir[N],cur[N],d[N];
    inline void add(int u,int v,int ww) {
      vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww;
      vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt,w[cnt]=0;
    }
    inline void adde(int u,int v,int ww) {
      vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,w[cnt]=ww;
      vr[++cnt]=u,nxt[cnt]=fir[v],fir[v]=cnt,w[cnt]=ww;
    }
    queue<int> q;
    inline bool bfs() {
    	memset(d,0,sizeof d),memcpy(cur,fir,sizeof cur);
    	d[s]=1,q.push(s); while(q.size()) {
    		R u=q.front(); q.pop();
    		for(R i=fir[u];i;i=nxt[i]) if(w[i]) {
    			R v=vr[i]; if(!d[v]) d[v]=d[u]+1,q.push(v);
    		}
    	} return d[t];
    }
    inline int dfs(int u,int f) {
    	if(u==t||f<=0) return f; R res=f;
    	for(R& i=cur[u];i;i=nxt[i]) if(w[i]) {
    		R v=vr[i]; if(d[v]==d[u]+1) {
    			R tmp=dfs(v,min(res,w[i]));
    			if(!tmp) d[v]=0;
    			res-=tmp,w[i]-=tmp,w[i^1]+=tmp;
    			if(!res) return f;
    		}
    	} return f-res;
    }
    inline int dinic() {R ret=0; while(bfs()) ret+=dfs(s,Inf); return ret;}
    #define p(i,j) ((i-1)*m+j)
    inline void main() {
      n=g(),m=g(),s=0,t=n*m+1;
      for(R i=1;i<=n;++i) for(R j=1;j<=m;++j)
        ans+=(a[i][j]=g()),a[i][j]<<=1;
      for(R i=1;i<=n;++i) for(R j=1;j<=m;++j)
        ans+=(b[i][j]=g()),b[i][j]<<=1;
      for(R i=1,x;i<n;++i) for(R j=1;j<=m;++j)
        x=g(),ans+=x,a[i][j]+=x,a[i+1][j]+=x,
        adde(p(i,j),p(i+1,j),x);
      for(R i=1,x;i<n;++i) for(R j=1;j<=m;++j)
        x=g(),ans+=x,b[i][j]+=x,b[i+1][j]+=x,
        adde(p(i,j),p(i+1,j),x);
      for(R i=1,x;i<=n;++i) for(R j=1;j<m;++j)
        x=g(),ans+=x,a[i][j]+=x,a[i][j+1]+=x,
        adde(p(i,j),p(i,j+1),x);
      for(R i=1,x;i<=n;++i) for(R j=1;j<m;++j)
        x=g(),ans+=x,b[i][j]+=x,b[i][j+1]+=x,
        adde(p(i,j),p(i,j+1),x);
      for(R i=1;i<=n;++i) for(R j=1;j<=m;++j)
        add(s,p(i,j),a[i][j]),add(p(i,j),t,b[i][j]);
      printf("%d
    ",ans-dinic()/2);
    }
    } signed main() {Luitaryi::main(); return 0;}
    
    

    2019.12.30

  • 相关阅读:
    [java]java String.split()函数的用法分析
    [sql]java.sql.Types的具体对应值(jdbcType)
    [sql]join的5种方式:inner join、left(outer) join、right (outer) Join、full(outer) join、cross join
    [java]String和Date、Timestamp之间的转换
    [Eclipse]保存java文件时,自动删除不需要的包import
    [postgresql]ROWS is not applicable when function does not return a set问题解决
    [postgreSql]postgreSql数据库、模式、表、函数的删除与创建
    zbb20170816 oracle Oracle 查看表空间、数据文件的大小及使用情况sql语句
    zbb20170811 mysql远程连接报错: Host * is not allowed to connect to this MySQL server,解决方法
    zbb20170811 linux 给用户授予文件夹权限
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12121555.html
Copyright © 2011-2022 走看看