P3254 圆桌问题

题解:源点向单位建容量为单位人数的边,桌子向汇点建容量为桌子最多容纳多少人的边,单位向所有桌子连容量为1的边,跑最大流。

如果最大流等于单位总人数则有解,输出满流边即为方案。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=450,M=(150*270+N)*2,inf=1e9;
 4 int h[N],e[M],ne[M],f[M],idx;
 5 int cur[N],d[N];
 6 int n,m,S,T;
 7 void add(int a,int b,int c)
 8 {
 9     ne[idx]=h[a],e[idx]=b,f[idx]=c,h[a]=idx++;
10     ne[idx]=h[b],e[idx]=a,f[idx]=0,h[b]=idx++;
11 }
12 bool bfs()
13 {
14     memset(d,-1,sizeof d);
15     queue<int>q;
16     d[S]=0;
17     q.push(S);
18     cur[S]=h[S];
19     while(q.size())
20     {
21         int t=q.front();
22         q.pop();
23         for(int i=h[t];i!=-1;i=ne[i])
24         {
25             int j=e[i];
26             if(d[j]==-1&&f[i])
27             {
28                 d[j]=d[t]+1;
29                 cur[j]=h[j];
30                 if(j==T)return true;
31                 q.push(j);
32             }
33         }
34     }
35     return false;
36 }
37 int find(int u,int limit)
38 {
39     if(u==T)return limit;
40     int flow=0;
41     for(int i=cur[u];i!=-1&&flow<limit;i=ne[i])
42     {
43         int j=e[i];
44         cur[u]=i;
45         if(d[j]==d[u]+1&&f[i])
46         {
47             int t=find(j,min(f[i],limit-flow));
48             if(!t)d[j]=-1;
49             f[i]-=t,f[i^1]+=t,flow+=t;
50         }
51     }
52     return flow;
53 }
54 int dinic()
55 {
56     int r=0,flow;
57     while(bfs())while(flow=find(S,inf))r+=flow;
58     return r;
59 }
60 int main()
61 {
62     memset(h,-1,sizeof h);
63     cin>>m>>n;
64     S=0,T=N-1;
65     int tot=0;
66     for(int i=1;i<=m;i++)
67     {
68         int x;
69         scanf("%d",&x);
70         add(S,i,x);
71         tot+=x;
72     }
73     for(int i=1;i<=n;i++)
74     {
75         int x;
76         scanf("%d",&x);
77         add(m+i,T,x);
78     }
79     for(int i=1;i<=m;i++)
80     for(int j=1;j<=n;j++)
81     add(i,m+j,1);
82     if(tot!=dinic())puts("0");
83     else
84     {
85         puts("1");
86         for(int i=1;i<=m;i++)
87         {
88         for(int j=h[i];j!=-1;j=ne[j])
89         {
90             int b=e[j];
91             if(b>=m+1&&b<=n+m&&!f[j])
92             printf("%d ",b-m);
93         }
94         printf("\n");
95         }
96     }
97 }

 

posted @ 2020-09-15 16:58  cumtljz  阅读(128)  评论(0编辑  收藏  举报