题目描述:
假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。
会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
这题和试题库问题没有太大本质上的区别。
建模:
由于特殊限制 每个单位只能在一个桌子坐一个人
所以我们就把每个单位向各个桌子连一道流量为1的边
由源点向每个单位连上 连上单位人数的边
由每个圆桌向汇点连上 圆桌人数的边
然后跑一下最大匹配 如果最大匹配数等于所有单位的人数和
那么就可以 完全安排 否则不能完全安排
dinic代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int INF=1e8,maX=151,mAX=301,MAX=5000001,Max=10001,t=10000; 4 struct p{ 5 int x,y,dis; 6 }c[MAX]; 7 int m,n,num,TOT,KING; 8 int h[Max],d[Max],r[maX]; 9 bool use[mAX]; 10 bool rou[maX][mAX]; 11 void add(int x,int y,int dis) 12 { 13 c[num].x=h[y];c[num].y=x;c[num].dis=0;h[y]=num++; 14 c[num].x=h[x];c[num].y=y;c[num].dis=dis;h[x]=num++; 15 } 16 bool bfs() 17 { 18 queue<int> qu; 19 qu.push(0); 20 memset(d,0,sizeof(d)); 21 d[0]=1; 22 while(!qu.empty()) 23 { 24 int tt=qu.front(); 25 qu.pop(); 26 for(int i=h[tt];i;i=c[i].x) 27 if(c[i].dis&&!d[c[i].y]) 28 { 29 d[c[i].y]=d[tt]+1; 30 qu.push(c[i].y); 31 } 32 } 33 return d[t]; 34 } 35 int dfs(int x,int dix) 36 { 37 if(x==t||!dix) return dix; 38 int sum=0; 39 for(int i=h[x];i;i=c[i].x) 40 if(d[c[i].y]==d[x]+1&&c[i].dis) 41 { 42 int dis=dfs(c[i].y,min(c[i].dis,dix)); 43 if(dis) 44 { 45 sum+=dis; 46 dix-=dis; 47 c[i].dis-=dis; 48 c[i^1].dis+=dis; 49 if(!dix) break; 50 } 51 } 52 if(!sum) d[x]=-1; 53 return sum; 54 } 55 int dinic() 56 { 57 int tot=0; 58 while(bfs()) 59 tot+=dfs(0,INF); 60 return tot; 61 } 62 int main() 63 { 64 scanf("%d%d",&m,&n); 65 for(int i=1;i<=m;i++) 66 { 67 scanf("%d",&r[i]); 68 add(0,i,r[i]); 69 for(int j=1;j<=n;j++) 70 add(i,j+m,1); 71 TOT+=r[i]; 72 } 73 //add(0,s,TOT); 74 //KING=num-1; 75 for(int i=1;i<=n;i++) 76 { 77 int x; 78 scanf("%d",&x); 79 add(i+m,t,x); 80 } 81 if(dinic()==TOT) printf("1 "); 82 else 83 { 84 printf("0"); 85 return 0; 86 } 87 for(int j=1;j<=m;j++) 88 for(int i=h[j];i;i=c[i].x) 89 if(c[i].y>=1+m&&c[i].y<=n+m&&!c[i].dis) 90 rou[j][c[i].y-m]=1; 91 for(int i=1;i<=m;i++) 92 { 93 memset(use,0,sizeof(use)); 94 for(int j=1;j<=r[i];j++) 95 for(int k=1;k<=n;k++) 96 if(!use[k]&&rou[i][k]) 97 { 98 use[k]=1; 99 printf("%d ",k); 100 break; 101 } 102 printf(" "); 103 } 104 return 0; 105 }