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\n",0);
135 return 0;
136 }
137 printf("%d\n",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 }