BZOJ2127:happiness(最小割)
2018-03-12 10:05
375 查看
题面
题意:一群人,每人选文选里都有收益,相邻两个人同时选文和选理也有收益
问最大收益
二选一,应该是网络流
网络流忘得差不多了
我刚看到的时候什么都想不出
二选一能处理的问题
①两个人选不同的有代价
②一群人选相同某个的收益(一群人中的某人不选有代价)
属于S集则选文,否则选理
只考虑两个人A,B
套①,看似无法处理共同的问题
可以把共同选文的收益平分加在与S相连的边上
共同选理的收益加在与T相连的边上
算出代价为(共同选文的收益+共同选理的收益)/2
根据套路,直接在A,B间连双向边
套②,就很显然了
有一人选了理就无法获得共同选文的收益
在图上:有一人属于T集,则要割一条连接S与A,B的边
新建一个点与A,B连通,且与S有一条容量为共同选文收益的边
选理也一样
一丢丢总结
对于某个点(除了拆点),永远与S和T分别有边
且这两条割且只割一条,决定了它选什么
除了上面两个问题,其他都是最小割不可做的(同选有代价,异选有收益)
网络流边从2开始标号
网络流边从2开始标号
题意:一群人,每人选文选里都有收益,相邻两个人同时选文和选理也有收益
问最大收益
二选一,应该是网络流
网络流忘得差不多了
我刚看到的时候什么都想不出
二选一能处理的问题
①两个人选不同的有代价
②一群人选相同某个的收益(一群人中的某人不选有代价)
属于S集则选文,否则选理
只考虑两个人A,B
套①,看似无法处理共同的问题
可以把共同选文的收益平分加在与S相连的边上
共同选理的收益加在与T相连的边上
算出代价为(共同选文的收益+共同选理的收益)/2
根据套路,直接在A,B间连双向边
套②,就很显然了
有一人选了理就无法获得共同选文的收益
在图上:有一人属于T集,则要割一条连接S与A,B的边
新建一个点与A,B连通,且与S有一条容量为共同选文收益的边
选理也一样
一丢丢总结
对于某个点(除了拆点),永远与S和T分别有边
且这两条割且只割一条,决定了它选什么
除了上面两个问题,其他都是最小割不可做的(同选有代价,异选有收益)
网络流边从2开始标号
网络流边从2开始标号
网络流边从2开始标号
#include <iostream> #include <fstream> #include <algorithm> #include <cmath> #include <ctime> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define mmst(a, b) memset(a, b, sizeof(a)) #define mmcp(a, b) memcpy(a, b, sizeof(b)) typedef long long LL; const int N=12345,M=2002000,oo=1e9+7; int n,m,ans,T; int wen[110][110],li[110][110],a[110][110]; int to[M],nex[M],cap[M],cnt=2; int head ,lter ,level ,q ; int p(int x,int y) { return (x-1)*m+y; } void add(int u,int v,int w,int rw) { to[cnt]=v; cap[cnt]=w; nex[cnt]=head[u]; head[u]=cnt++; to[cnt]=u; cap[cnt]=rw; nex[cnt]=head[v]; head[v]=cnt++; } bool bfs() { q[1]=0; mmcp(lter,head); mmst(level,-1); level[0]=1; int hh=1,tt=1; for(;hh<=tt;) { int hy=q[hh++]; for(int h=head[hy];h;h=nex[h]) if(cap[h]&&level[to[h]]<0) { q[++tt]=to[h]; level[to[h]]=level[hy]+1; } } return level[T]>0; } int dfs(int v,int f) { if(v==T||!f) return f; int ret=0; for(int &h=lter[v];h;h=nex[h]) if(cap[h]&&level[to[h]]>level[v]) { int d=dfs(to[h],min(f,cap[h])); ret+=d; cap[h]-=d; cap[h^1]+=d; f-=d; if(!f) break; } return ret; } int main() { cin>>n>>m; T=n*m+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&wen[i][j]),wen[i][j]<<=1,ans+=wen[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&li[i][j]),li[i][j]<<=1,ans+=li[i][j]; for(int i=1;i<=n-1;i++) for(int j=1;j<=m;j++) { scanf("%d",&a[i][j]); ans+=a[i][j]+a[i][j]; wen[i][j]+=a[i][j]; wen[i+1][j]+=a[i][j]; } for(int i=1;i<=n-1;i++) for(int j=1;j<=m;j++) { int x; scanf("%d",&x); ans+=x+x; add(p(i,j),p(i+1,j),a[i][j]+x,a[i][j]+x); li[i][j]+=x; li[i+1][j]+=x; } for(int i=1;i<=n;i++) for(int j=1;j<=m-1;j++) { scanf("%d",&a[i][j]); ans+=a[i][j]+a[i][j]; wen[i][j]+=a[i][j]; wen[i][j+1]+=a[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=m-1;j++) { int x; scanf("%d",&x); ans+=x+x; add(p(i,j),p(i,j+1),a[i][j]+x,a[i][j]+x); li[i][j]+=x; li[i][j+1]+=x; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { add(0,p(i,j),wen[i][j],0); add(p(i,j),T,li[i][j],0); } int flow=0; while(bfs()) ans-=dfs(0,oo); cout<<ans/2<<endl; return 0; }
相关文章推荐
- bzoj2127 happiness(最小割)
- bzoj2127: happiness 浅析一类最小割问题——二元关系的应用
- bzoj2127: happiness(最小割)
- bzoj2127: happiness 最小割
- bzoj2127 happiness 最小割
- [bzoj2127]happiness——最小割
- 【BZOJ2127】happiness 最小割 自己YY出来的建图、
- 2127: happiness 最小割
- bzoj 2127 happiness(最小割)
- BZOJ 2127 : happiness 疯了的最小割
- 【BZOJ2127】happiness(最小割)
- BZOJ 2127: happiness 最小割 二元组建图
- BZOJ 2127: happiness(最小割解决集合划分)
- bzoj2127 happiness
- bzoj2127: happiness
- BZOJ2127 happiness-最小割
- BZOJ2127 happiness-最小割
- BZOJ 2127: happiness(最小割)
- BZOJ2127 happiness
- 最小割 [国家集训队2011]happiness(吴确)