网络流24题——圆桌问题

题目描述:

假设有来自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\n");
 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("\n");
103       }
104     return 0;
105 }
View Code

猜你喜欢

转载自www.cnblogs.com/71-111/p/9339503.html
今日推荐