【BZOJ2127】happiness 最小割 自己YY出來的建圖、

來源:互聯網
上載者:User

標籤:bzoj2127   happiness   最小割   

轉載請註明出處:http://blog.csdn.net/vmurder/article/details/42609669

其實我就是覺得原創的訪問量比未授權盜版多有點不爽233。。。


那個一看就覺得不是費用流就是最小割。

想想就確定最小割了。


    考慮到一個人,文理不可兼得,不妨先建點,然後向源點(文科),匯點(理科)連邊,流量(也就是割)是對應喜悅值。(這裡的想法是先建個差不多的,有漏洞再拆點啊,建輔助點啊什麼的)


    然後再考慮一對朋友之間的共文理喜悅值:

如果都選文,那麼需要割掉雙方都選理的喜悅值,

如果都選理,那麼需要割掉雙方都選文的喜悅值,

如果一文一理,那麼就都割。


首先對於一個點對,我們考慮到他們之間的關係只在雩都選文或者都選理的喜悅值,

而求最小割時我們要割掉這部分權值,那麼我們可以建邊,然後把邊進行處理。


一、

首先我最開始的想法是把邊的權值設定為都選文+都選理的和。

這樣就成功地滿足了一文一理的情況。

但是卻無法分開。


二、

這時候我們可以把邊建成點,然後兩邊的人向此點連容量inf的無向邊,

然後源點(文科)向此點連都選文的容量,匯點連都選理的。

這樣我們就滿足了都選文或者都選理的情況。

也就是都選文的話,我們就可以不割“都選文”這種權值,都選理 同理。

但是這是WA的,cheat也不行(實測),因為我們又無法讓兩人一文一理了。


三、

再往“一”那裡考慮,發現我們有時需要把兩種權值都割斷。

這個時候想到:

a-(len)-->b,當len值一定,把圖建成a-->b-->c-->d,只要邊長都是len,那麼最小割是不變的。


所以我們把“邊點”拆成兩個點,一個對應S集(文),一個對應T集(理),,

這樣我們就可以把原來的inf也改成對應權值,使得割斷哪一條邊都是最小割值。

這麼說可能有些含糊,不妨來張圖。


這張圖就是建法,不妨簡單分析一下就可以理解為什麼了。

貼代碼:

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 50005#define M 300000#define P 105#define inf 0x3f3f3f3fusing namespace std;struct KSD{int v,len,next;}e[M];int head[N],cnt;inline void add(int u,int v,int len){e[++cnt].v=v;e[cnt].len=len;e[cnt].next=head[u];head[u]=cnt;e[++cnt].v=u;e[cnt].len=len;e[cnt].next=head[v];head[v]=cnt;}int s,t,d[N];queue<int>q;bool bfs(){while(!q.empty())q.pop();memset(d,0,sizeof(d));int i,u,v;q.push(s),d[s]=1;while(!q.empty()){u=q.front(),q.pop();for(i=head[u];i;i=e[i].next){v=e[i].v;if(!d[v]&&e[i].len){d[v]=d[u]+1;if(v==t)return 1;q.push(v);}}}return 0;}int dinic(int x,int flow){if(x==t)return flow;int remain=flow,i,v,k;for(i=head[x];i&&remain;i=e[i].next){v=e[i].v;if(d[v]==d[x]+1&&e[i].len){k=dinic(v,min(remain,e[i].len));if(!k)d[v]=0;e[i].len-=k,e[i^1].len+=k;remain-=k;}}return flow-remain;}int n,m,id[P][P];int sum,maxflow;void build(){int i,j,a,temp;scanf("%d%d",&n,&m),temp=n*m;s=n*m+2*(n-1)*m+2*n*(m-1)+1,t=n*m+2*(n-1)*m+2*n*(m-1)+2;for(i=1;i<=n;i++)for(j=1;j<=m;j++)id[i][j]=++cnt;cnt=1;// 第一個矩陣為n行m列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學選擇文科獲得的喜悅值。for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&a);sum+=a;add(s,id[i][j],a);}// 第二個矩陣為n行m列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學選擇理科獲得的喜悅值。for(i=1;i<=n;i++)for(j=1;j<=m;j++){scanf("%d",&a);sum+=a;add(id[i][j],t,a);}// 第三個矩陣為n-1行m列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學與第i+1行第j列的同學同時選擇文科獲得的額外喜悅值。for(i=1;i<n;i++)for(j=1;j<=m;j++){scanf("%d",&a);sum+=a,++temp;add(id[i][j],temp,a),add(id[i+1][j],temp,a);add(s,temp,a);}// 第四個矩陣為n-1行m列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學與第i+1行第j列的同學同時選擇理科獲得的額外喜悅值。for(i=1;i<n;i++)for(j=1;j<=m;j++){scanf("%d",&a);sum+=a,++temp;add(id[i][j],temp,a),add(id[i+1][j],temp,a);add(temp,t,a);}// 第五個矩陣為n行m-1列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學與第i行第j+1列的同學同時選擇文科獲得的額外喜悅值。for(i=1;i<=n;i++)for(j=1;j<m;j++){scanf("%d",&a);sum+=a,++temp;add(id[i][j],temp,a),add(id[i][j+1],temp,a);add(s,temp,a);}// 第六個矩陣為n行m-1列 此矩陣的第i行第j列的數字表示座位在第i行第j列的同學與第i行第j+1列的同學同時選擇理科獲得的額外喜悅值。for(i=1;i<=n;i++)for(j=1;j<m;j++){scanf("%d",&a);sum+=a,++temp;add(id[i][j],temp,a),add(id[i][j+1],temp,a);add(temp,t,a);}}int main(){//freopen("test.in","r",stdin);build();while(bfs())maxflow+=dinic(s,inf);printf("%d\n",sum-maxflow);return 0;}



【BZOJ2127】happiness 最小割 自己YY出來的建圖、

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.