P2055-假期的宿舍【网络流,最大流,最大匹配】
生活随笔
收集整理的這篇文章主要介紹了
P2055-假期的宿舍【网络流,最大流,最大匹配】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
鏈接:
https://www.luogu.org/record/show?rid=7930976
大意
有n個人,有的在學校有床有的沒有,有的在家有的沒有。現在如果有人回家了那么他就會去看望他的朋友,回家的就會空出自己的床位。每個人可以睡和自己是直接朋友關系或自己的床,要求給本來有床的并且不在家的和來看望其的朋友分配床位。
解題思路
將人和床建立二分圖,我們假設每個在家的人都有床,這樣不用看望朋友的就可以睡自己床,然后將除了沒有床且不再家的人都作為左邊點,然后將在學校的床作為右邊點進行最大匹配。
代碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct line{int to,next,w; }a[10010]; int n,m,x,y,d[110],tot,state[110],school[110],num; int head,tail,ls[110],s,e,ans,t,home[110],nn,qn; bool ok[110],lxx[110][110]; void addl(int x,int y,int w) {a[tot].to=y;a[tot].next=ls[x];a[tot].w=w;ls[x]=tot++;a[tot].to=x;a[tot].next=ls[y];a[tot].w=0;ls[y]=tot++; } bool bfs() {head=0;tail=1;memset(d,-1,sizeof(d));d[s]=0;state[1]=s;do{head++;int x=state[head];for (int q=ls[x];q;q=a[q].next){int y=a[q].to;if (a[q].w>0 && d[y]==-1){d[y]=d[x]+1;state[++tail]=y;if (y==e) return true;}}}while (head<tail);return false; } int dinic(int x,int flow) {int rest=0,k;if (x==e) return flow;for (int q=ls[x];q;q=a[q].next){int y=a[q].to;if (a[q].w>0 && d[y]==d[x]+1){rest+=(k=dinic(y,min(a[q].w,flow-rest)));a[q].w-=k;a[q^1].w+=k;if (rest==flow) return flow;}}if (!rest) d[x]=0;return rest; } int main() {scanf("%d",&t);for (int ti=1;ti<=t;ti++){memset(ls,0,sizeof(ls));e=105;s=104;tot=2;num=0;scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&school[i]);if(school[i]) addl(i+n,e,1);//床}for (int i=1;i<=n;i++){scanf("%d",&home[i]);if (!school[i]||(school[i]&&!home[i])) addl(s,i,1),num++;//需要匹配的人}for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){scanf("%d",&x);if (x||i==j)addl(i,j+n,1);//和自己或直接朋友的床匹配}}ans=0;while (bfs()) ans+=dinic(s,2147483647);if (ans==num) printf("^_^\n");else printf("T_T\n");} }小技巧
其實有些時候可以將本來不需要的在其他地方分配掉可能可以降低難度
總結
以上是生活随笔為你收集整理的P2055-假期的宿舍【网络流,最大流,最大匹配】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多年以后我还能不能活着出自什么歌 多年以
- 下一篇: P2698-花盆Flowerpot【单调