日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[BZOJ 3894]文理分科(最小割)

發布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [BZOJ 3894]文理分科(最小割) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

文理分科是一件很糾結的事情!(雖然看到這個題目的人肯定都沒有糾結過)

小P所在的班級要進行文理分科。他的班級可以用一個n*m的矩陣進行 描述,每個格子代表一個同學的座位。每位同學必須從文科和理科中選擇 一科。同學們在選擇科目的時候會獲得一個滿意值。滿意值按如下的方式 得到: 1.如果第i行第秒J的同學選擇了文科,則他將獲得art[i][j]的滿意值,如 果選擇理科,將得到science[i][j]的滿意值。 2.如果第i行第J列的同學選擇了文科,并且他相鄰(兩個格子相鄰當且 僅當它們擁有一條相同的邊)的同學全部選擇了文科,則他會更開 心,所以會增加same_art[i][j]的滿意值。 3.如果第i行第j列的同學選擇了理科,并且他相鄰的同學全部選擇了理 科,則增加same_science[i][j]的滿意值。 小P想知道,大家應該如何選擇,才能使所有人的滿意值之和最大。請 告訴他這個最大值。

Solution

?妹主席在JZYZ講過的一道,想起來了于是去切一下

“依然是把最大化收益轉化為最小化得不到的收益。
對于每個點,向S和T分別連容量為ai,bi的邊,那么V代表劃分到A集合的點,V’代表c[s,V’]代表劃分到B集合中的元素失去的ai收益,c[V,t]相反,因為選到A集合的點和選到B集合的點相互之間不會產生影響,所以c[V,V’]=0
對于每個附加條件我們額外建立一個點,假設是要求一些元素必須劃分到A集合中,那么從源點向它連一條容量為ci的邊,從它向要求的元素連一條容量為正無窮的邊,這樣,割掉源點連向它的邊(舍棄掉這個收益)和割掉它連向的所有點連向匯點的邊(舍棄掉這些點劃分到bi的收益)必須選擇其中一個。
點數為O(n+m),邊數為O(n+m+sigma(|S|))”
——妹主席的教誨

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #define Max(a,b) (a>b?a:b) #define Min(a,b) (a<b?a:b) #define INF 0x3f3f3f3f using namespace std; int n,m,s,t,level[50005],head[50005],cnt=0,ans=0; int dx[5]={1,-1,0,0,0},dy[5]={0,0,1,-1,0}; struct Node{int next,to,cap; }Edges[1000005]; int Read() {int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } void addedge(int u,int v,int c) {Edges[cnt].next=head[u];head[u]=cnt;Edges[cnt].to=v;Edges[cnt++].cap=c; } void Insert(int u,int v,int c) {addedge(u,v,c);addedge(v,u,0); } int number(int i,int j) {return (i-1)*m+j; } bool bfs() {memset(level,-1,sizeof(level));queue<int>q;q.push(s);level[s]=0;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];~i;i=Edges[i].next){int v=Edges[i].to;if(level[v]==-1&&Edges[i].cap)level[v]=level[u]+1,q.push(v);}}if(level[t]==-1)return false;return true; } int dfs(int u,int Maxflow) {if(u==t)return Maxflow;int flow=0,d;for(int i=head[u];~i&&Maxflow>flow;i=Edges[i].next){int v=Edges[i].to;if(level[v]==level[u]+1&&Edges[i].cap){d=dfs(v,Min(Maxflow-flow,Edges[i].cap));Edges[i].cap-=d;Edges[i^1].cap+=d;flow+=d;}}if(!flow)level[u]=-1;return flow; } int Dinic() {int res=0,d;while(bfs()){while(d=dfs(s,INF))res+=d;}return res; } int main() {memset(head,-1,sizeof(head));n=Read(),m=Read();s=0,t=3*n*m+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int art=Read();ans+=art;Insert(s,number(i,j),art);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int science=Read();ans+=science;Insert(number(i,j),t,science);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int same_art=Read(),p=number(i,j)+m*n;ans+=same_art;Insert(s,p,same_art);for(int k=0;k<5;k++){if(i+dx[k]>0&&i+dx[k]<=n&&j+dy[k]>0&&j+dy[k]<=m)Insert(p,number(i+dx[k],j+dy[k]),INF);}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int same_science=Read(),p=number(i,j)+2*m*n;ans+=same_science;Insert(p,t,same_science);for(int k=0;k<5;k++){if(i+dx[k]>0&&i+dx[k]<=n&&j+dy[k]>0&&j+dy[k]<=m)Insert(number(i+dx[k],j+dy[k]),p,INF);}}printf("%d\n",ans-Dinic());return 0; }

?

轉載于:https://www.cnblogs.com/Zars19/p/6694937.html

總結

以上是生活随笔為你收集整理的[BZOJ 3894]文理分科(最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。