圆桌问题 【网络流24题】

 

 

 

 

 

 

思路

  题目已经给出了暗示

  即题目中给出了一个二分图

  显然,可以把人和桌子作为二分图的两个阵营

  由于题目中给出的限制:每个单位的人都必须坐在不同的桌子上

  所以把单位向每个桌子连一条流量为1的边

  由S向单位连单位人数的边 

  由桌子向T连桌子容量的边  

  然后跑一次最大流,最后枚举每个单位的邻接边,通过判断残量网络上的值可以求出这个人去了哪张桌子

  朴素的Dinic会T最后一个点

  考虑当前弧优化来优化朴素Dinic算法,只需要70ms即可跑完

 

CODE

 

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << "=" << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 
  9 const int inf = 0x3f3f3f3f;
 10 
 11 template<class T>inline void read(T &res)
 12 {
 13     char c;T flag=1;
 14     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
 15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
 16 }
 17 
 18 namespace _buff {
 19     const size_t BUFF = 1 << 19;
 20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
 21     char getc() {
 22         if (ib == ie) {
 23             ib = ibuf;
 24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
 25         }
 26         return ib == ie ? -1 : *ib++;
 27     }
 28 }
 29 
 30 int qread() {
 31     using namespace _buff;
 32     int ret = 0;
 33     bool pos = true;
 34     char c = getc();
 35     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
 36         assert(~c);
 37     }
 38     if (c == '-') {
 39         pos = false;
 40         c = getc();
 41     }
 42     for (; c >= '0' && c <= '9'; c = getc()) {
 43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
 44     }
 45     return pos ? ret : -ret;
 46 }
 47 
 48 const int maxn = 5e4 + 7;
 49 
 50 int s, t, cnt = 1;
 51 int head[maxn << 1], edge[maxn << 1], nxt[maxn << 1], vis[maxn << 1];
 52 int w[maxn << 1];//残量网络
 53 int rev[maxn << 1];
 54 int depth[maxn << 1];//图层
 55 int n, m;
 56 int cur[maxn << 1];//当前弧优化
 57 
 58 void BuildGraph(int u, int v, int cap) {
 59     ++cnt;
 60     edge[cnt] = v;
 61     nxt[cnt] = head[u];
 62     rev[cnt] = cnt + 1;
 63     w[cnt] = cap;
 64     head[u] = cnt;
 65 
 66     ++cnt;
 67     edge[cnt] = u;
 68     nxt[cnt] = head[v];
 69     w[cnt] = 0;
 70     rev[cnt] = cnt - 1;
 71     head[v] = cnt;
 72 }
 73 
 74 bool bfs(int x) {
 75     queue<int> q;
 76     for ( int i = 0; i <= t; ++i ) {
 77         cur[i] = head[i];
 78     }
 79     while(!q.empty()) {
 80         q.pop();
 81     }
 82     memset(depth, 63, sizeof(depth));
 83     depth[s] = 0;
 84     q.push(s);
 85     do {
 86         int u = q.front();
 87         q.pop();
 88         for ( int i = head[u]; i; i = nxt[i] ) {
 89             int v = edge[i];
 90             if(w[i] > 0 && depth[u] + 1 < depth[v]) {
 91                 depth[v] = depth[u] + 1;
 92                 q.push(v);
 93                 if(v == t) {
 94                     return true;
 95                 }
 96             }
 97         }
 98     } while (!q.empty());
 99     if(depth[t] < inf)
100         return true;
101     return false;
102 }
103 
104 int dfs(int u, int dist) {
105     if(!dist || u == t) {
106         return dist;
107     }
108     int flow = 0, f;
109     for ( int i = cur[u]; i; i = nxt[i] ) {
110         cur[u] = 1;
111         int v = edge[i];
112         if(depth[v] == depth[u] + 1 && (f = dfs(v, min(dist, w[i])))) {
113             flow += f;
114             dist -= f;
115             w[i] -= f;
116             w[i ^ 1] += f;
117             if(!dist)
118                 break;
119         }
120     }
121     return flow;
122 }
123 
124 int pp[maxn];
125 int table[maxn];
126 int sum = 0;
127 
128 int main()
129 {
130     //freopen("data.txt", "r", stdin);
131     read(m); read(n);
132     for ( int i = 1; i <= m; ++i ) {
133         read(pp[i]);
134         sum += pp[i];
135     }
136     for ( int i = 1; i <= n; ++i ) {
137         read(table[i]);
138     }
139     s = 0, t = n + m + 1;
140     for ( int i = 1; i <= m; ++i ) {
141         BuildGraph(s, i, pp[i]);
142         for ( int j = 1; j <= n; ++j ) {
143             BuildGraph(i, j + m, 1);
144         }
145     }
146     for ( int i = 1; i <= n; ++i ) {
147         //printf("table[%d]:%d\n",i, table[i]);
148         BuildGraph(i + m, t, table[i]);
149     }   
150     //dbg(sum);
151     int ans = 0;
152     while(bfs(s)) {
153         ans += dfs(0, 0x7f7f7f7f);
154     }
155     //dbg(ans);
156     if(sum != ans) {
157         puts("0");
158     }
159     else {
160         cout << 1 << endl;
161         for ( int i = 1; i <= m; ++i ) {
162             for ( int j = head[i]; j; j = nxt[j] ) {
163                 int to = edge[j];
164                 if(to != t && !w[j]) {
165                     printf("%d ",to - m);
166                     //printf("cap[%d]:%d\n",j, w[j]);
167                 }
168             }
169             puts("");
170         }
171     }
172     return 0;
173 }
View Code

 

posted @ 2020-05-04 19:37  Orangeko  阅读(139)  评论(0编辑  收藏  举报