首页 > 代码库 > URAL 1774 Barber of the Army of Mages 最大流

URAL 1774 Barber of the Army of Mages 最大流

思路:

  以理发的次数当容量,源点到每个人建一条容量为2的边,人到他可达的每个时间点建一条边,每个时间点到汇点建一条容量为m的边。然后判断最大流是否等于2*n。

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <queue>
  9 #include <stack>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <functional>
 14 #include <time.h>
 15 
 16 using namespace std;
 17 
 18 
 19 using namespace std;
 20 
 21 const int INF = 1<<30;
 22 const int MAXN = 3000;
 23 const int MAXE = (int)5e5+10;
 24 
 25 struct Dinic{
 26     struct Edge {
 27         int from, to, cap, flow;
 28         //从from到to的容量为cap,流量为flow的弧
 29     };
 30 
 31     int n, m, s, t; //结点数,边数(包括反向弧),源点,汇点
 32     vector<Edge> edges; //边表。 edges[e]和edges[e^1]互为反向弧
 33     vector<int> G[MAXN]; //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
 34     bool vis[MAXN]; //bfs使用
 35     int d[MAXN]; //从起点到i的距离
 36     int cur[MAXN]; //当前弧下标
 37 
 38     inline void init() {
 39         edges.clear();
 40         for (int i = 0; i <= n; i++) {
 41             G[i].clear();
 42         }
 43     }
 44 
 45     inline void addEdge(int from, int to, int cap) {
 46         edges.push_back((Edge){from, to, cap, 0});
 47         edges.push_back((Edge){to, from, 0, 0});
 48         m = edges.size();
 49         G[from].push_back(m-2);
 50         G[to].push_back(m-1);
 51     }
 52 
 53     bool bfs() {
 54         memset(vis, false, sizeof(vis));
 55         queue<int> q;
 56         q.push(s);
 57         d[s] = 0;
 58         vis[s] = true;
 59 
 60         while (!q.empty()) {
 61             int u = q.front(); q.pop();
 62             for (int i = 0; i < G[u].size(); i++) {
 63                 Edge &e = edges[G[u][i]];
 64                 if (!vis[e.to] && (e.cap > e.flow)) { //只考虑残量网络中的弧
 65                     vis[e.to] = true;
 66                     d[e.to] = d[u]+1;
 67                     q.push(e.to);
 68                 }
 69             }
 70         }
 71         return vis[t];
 72     }
 73 
 74     int dfs(int u, int c) {
 75         if (u==t || 0==c) return c;
 76         int flow = 0, f;
 77         for (int &i = cur[u]; i < G[u].size(); i++) { //从上次考虑的弧
 78             Edge &e = edges[G[u][i]];
 79             if ((d[u]+1)==d[e.to] && (f = dfs(e.to, min(c, e.cap-e.flow))) > 0) {
 80                 e.flow += f;
 81                 edges[G[u][i]^1].flow -= f;
 82                 flow += f;
 83                 c -= f;
 84                 if (0==c) break;
 85             }
 86         }
 87         return flow;
 88     }
 89 
 90     int MaxFlow(int s, int t) {
 91         this->s = s; this->t = t;
 92         int flow = 0;
 93         while (bfs()) {
 94             memset(cur, 0, sizeof(cur));
 95             flow += dfs(s, INF);
 96         }
 97         return flow;
 98     }
 99     void print(int st, int ed) {
100         for (int i = st; i < ed; i++) {
101             bool flag = false;
102             for (int j = 0; j < G[i].size(); j++) {
103                 Edge &e = edges[G[i][j]];
104                 if (e.flow==1) {
105                     if (flag) printf(" ");
106                     printf("%d", e.to);
107                     if (flag) {
108                         puts("");
109                         break;
110                     }
111                     flag = true;
112                 }
113             }
114         }
115     }
116 };
117 
118 Dinic a;
119 int n, m;
120 
121 void solve() {
122     // 时间点: 0~2000
123     // 人: 2001~2000+n
124     //s: 0, t: 2001+n
125     int s = 2001+n;
126     int t = s+1;
127     a.n = t;
128     a.init();
129     int x, y;
130     int Max = 0;
131     for (int i = 0; i < n; i++)
132         a.addEdge(s, 2001+i, 2);
133 
134     for (int i = 0; i < n; i++) {
135         scanf("%d%d", &x, &y);
136         Max = max(Max, x+y);
137         for (int j = 0; j < y; j++) {
138             a.addEdge(2001+i, x+j, 1);
139         }
140     }
141     for (int i = 0; i <= Max; i++)
142         a.addEdge(i, t, m);
143     int ans = a.MaxFlow(s, t);
144     if (2*n==ans) {
145         puts("Yes");
146         a.print(2001, 2001+n);
147     } else
148         puts("No");
149 }
150 
151 int main() {
152     #ifdef Phantom01
153         freopen("A.txt", "r", stdin);
154     #endif // Phantom01
155 
156     while (scanf("%d%d", &n, &m)!=EOF) {
157         solve();
158     }
159 
160     return 0;
161 }
View Code

其实做这个题,是为了检验更学的新模板 Dinic