LuoguP3254 圆桌问题(最大流)

题目描述

假设有来自m 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri (i =1,2,……,m)。

会议餐厅共有n 张餐桌,每张餐桌可容纳ci (i =1,2,……,n)个代表就餐。

为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,给出满足要求的代表就餐方案。

对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。

输入输出格式

输入格式:

第1 行有2 个正整数m 和n,m 表示单位数,n 表示餐桌数,1<=m<=150, 1<=n<=270。

第2 行有m 个正整数,分别表示每个单位的代表数。

第3 行有n 个正整数,分别表示每个餐桌的容量。

输出格式:

如果问题有解,第1 行输出1,否则输出0。接下来的m 行给出每个单位代表的就餐桌号。如果有多个满足要求的方案,只要输出1 个方案。

解题思路:

建立源点汇点。

源点向公司连边流量为公司人数。

公司向餐桌连边流量为$1$

餐桌向汇点连边流量为就餐人数上限。

最大流跑一下就好了。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 const int oo=0x3f3f3f3f;
  5 namespace stb{
  6     template<class tnt>
  7     class queue{
  8         #define INF 1000000
  9         public:
 10             queue(){h=1;t=0;}
 11             int nxt(int x){if(x+1==INF)return 1;return x+1;}
 12             void clear(void){h=1;t=0;}
 13             void push(tnt x){t=nxt(t);l[t]=x;}
 14             void pop(void){h=nxt(h);}
 15             tnt front(void){return l[h];}
 16             bool empty(void){return nxt(t)==h;}
 17         private:
 18             tnt l[INF];
 19             int h,t;
 20         #undef INF
 21     };
 22 };
 23 struct pnt{
 24     int hd;
 25     int lyr;
 26     int now;
 27 }p[10000];
 28 struct ent{
 29     int twd;
 30     int lst;
 31     int vls;
 32 }e[100000];
 33 int cnt;
 34 int n,m;
 35 int s,t;
 36 int N;
 37 stb::queue<int>Q;
 38 void ade(int f,int t,int v)
 39 {
 40     cnt++;
 41     e[cnt].twd=t;
 42     e[cnt].vls=v;
 43     e[cnt].lst=p[f].hd;
 44     p[f].hd=cnt;
 45     return ;
 46 }
 47 bool Bfs(void)
 48 {
 49     Q.clear();
 50     for(int i=1;i<=N;i++)
 51         p[i].lyr=0;
 52     p[s].lyr=1;
 53     Q.push(s);
 54     while(!Q.empty())
 55     {
 56         int x=Q.front();
 57         Q.pop();
 58         for(int i=p[x].hd;i;i=e[i].lst)
 59         {
 60             int to=e[i].twd;
 61             if(p[to].lyr==0&&e[i].vls>0)
 62             {
 63                 p[to].lyr=p[x].lyr+1;
 64                 if(to==t)
 65                     return true;
 66                 Q.push(to);
 67             }
 68         }
 69     }
 70     return false;
 71 }
 72 int Dfs(int x,int fll)
 73 {
 74     if(x==t)
 75         return fll;
 76     for(int& i=p[x].now;i;i=e[i].lst)
 77     {
 78         int to=e[i].twd;
 79         if(p[to].lyr==p[x].lyr+1&&e[i].vls>0)
 80         {
 81             int ans=Dfs(to,std::min(fll,e[i].vls));
 82             if(ans>0)
 83             {
 84                 e[i].vls-=ans;
 85                 e[((i-1)^1)+1].vls+=ans;
 86                 return ans;
 87             }
 88         }
 89     }
 90     return 0;
 91 }
 92 int Dinic(void)
 93 {
 94     int ans=0;
 95     while(Bfs())
 96     {
 97         for(int i=1;i<=N;i++)
 98             p[i].now=p[i].hd;
 99         int dlt;
100         while(dlt=Dfs(s,oo))
101             ans+=dlt;
102     }
103     return ans;
104 }
105 int main()
106 {
107     scanf("%d%d",&n,&m);
108     s=n+m+1;
109     t=s+1;
110     N=t;
111     int sum=0;
112     for(int i=1;i<=n;i++)
113     {
114         int v;
115         scanf("%d",&v);
116         sum+=v;
117         ade(s,i,v);
118         ade(i,s,0);
119         for(int j=m;j;j--)
120         {
121             ade(i,j+n,1);
122             ade(j+n,i,0);
123         }
124     }
125     for(int i=1;i<=m;i++)
126     {
127         int v;
128         scanf("%d",&v);
129         ade(i+n,t,v);
130         ade(t,i+n,v);
131     }
132     if(Dinic()!=sum)
133     {
134         printf("%d
",0);
135         return 0;
136     }
137     printf("%d
",1);
138     for(int i=1;i<=n;i++)
139     {
140         for(int j=p[i].hd;j;j=e[j].lst)
141         {
142             int to=e[j].twd;
143             if(to>n&&e[j].vls==0)
144                 printf("%d ",to-n);
145         }
146         puts("");
147     }
148     return 0;
149 }

 

原文地址:https://www.cnblogs.com/blog-Dr-J/p/10205395.html