[题解]poj 1274 The Perfect Stall(网络流)

Posted 阿波罗2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解]poj 1274 The Perfect Stall(网络流)相关的知识,希望对你有一定的参考价值。

二分匹配传送门[here]

原题传送门[here]


  题意大概说一下,就是有N头牛和M个牛棚,每头牛愿意住在一些牛棚,求最大能够满足多少头牛的要求。

  很明显就是一道裸裸的二分图最大匹配,但是为了练练网络流(做其它的题的时候,神奇地re掉了,于是就写基础题了)的最大流算法,就做做这道题。

  每一个牛都可一看成是个源点,每一个牛棚都可以看成是个汇点,但是一个网络应该只有一个汇点和一个源点才对,于是构造一个连接每个牛的超级源点,一个连接每个牛棚的超级汇点,每条边的容量为1,然后最大流Dinic算法(其它最大流算法也行)就行了。

Code极其不简洁的代码

  1 /**
  2  * poj.org
  3  * Problem#1274
  4  * Accepted
  5  * Time:16ms
  6  * Memory:1980k
  7  */
  8 #include<iostream>
  9 #include<sstream>
 10 #include<cstdio>
 11 #include<cmath>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<cctype>
 15 #include<ctime>
 16 #include<queue>
 17 #include<set>
 18 #include<map>
 19 #include<stack>
 20 #include<vector>
 21 #include<algorithm>
 22 using namespace std;
 23 typedef bool boolean;
 24 #define smin(a, b) (a) = min((a), (b))
 25 #define smax(a, b) (a) = max((a), (b))
 26 #define INF 0xfffffff
 27 template<typename T>
 28 inline boolean readInteger(T& u){
 29     char x;
 30     int aFlag = 1;
 31     while(!isdigit((x = getchar())) && x != \'-\' && ~x);
 32     if(!(~x))    return false;
 33     if(x == \'-\'){
 34         aFlag = -1;
 35         x = getchar();
 36     }
 37     for(u = x - \'0\'; isdigit((x = getchar())); u = u * 10 + x - \'0\');
 38     ungetc(x, stdin);
 39     u *= aFlag;
 40     return true;
 41 }
 42 ///map template starts
 43 typedef class Edge{
 44     public:
 45         int end;
 46         int next;
 47         int cap;
 48         int flow;
 49         Edge(const int end = 0, const int next = 0, const int cap = 0, const int flow = 0):end(end), next(next), cap(cap), flow(flow){}
 50 }Edge;
 51 
 52 typedef class MapManager{
 53     public:
 54         int ce;
 55         int *h;
 56         Edge *edge;
 57         MapManager(){}
 58         MapManager(int points, int limit):ce(0){
 59             h = new int[(const int)(points + 1)];
 60             edge = new Edge[(const int)(limit + 1)];
 61             memset(h, 0, sizeof(int) * (points + 1));
 62         }
 63         inline void addEdge(int from, int end, int cap, int flow){
 64             edge[++ce] = Edge(end, h[from], cap, flow);
 65             h[from] = ce;
 66         }
 67         inline void addDoubleEdge(int from, int end, int cap){
 68             addEdge(from, end, cap, 0);
 69             addEdge(end, from, cap, cap);
 70         }
 71         Edge& operator [](int pos){
 72             return edge[pos];
 73         }
 74         inline int reverse(int pos){        //反向边 
 75             return (pos & 1) ? (pos + 1) : (pos - 1);
 76         }
 77         inline void clear(){
 78             delete[] edge;
 79             delete h;
 80             ce = 0;
 81         }
 82 }MapManager;
 83 
 84 #define m_begin(g, i)     (g).h[(i)]
 85 #define m_end(g, i)     (g).edge[(i)].end
 86 #define m_next(g, i)     (g).edge[(i)].next
 87 #define m_cap(g, i)     (g).edge[(i)].cap
 88 #define m_flow(g, i)     (g).edge[(i)].flow
 89 ///map template ends
 90 
 91 int n, m;
 92 int t;
 93 MapManager g;
 94 
 95 inline boolean init(){
 96     if(!readInteger(n))    return false;
 97     readInteger(m);
 98     t = n + m + 1; 
 99     g = MapManager(t + 1, (n + 1) * (m + 1) * 2);
100     for(int i = 1, a, b; i <= n; i++){
101         readInteger(a);
102         while(a--){
103             readInteger(b);
104             g.addDoubleEdge(i, b + n, 1);
105         }
106     }
107     for(int i = 1; i <= n; i++)
108         g.addDoubleEdge(0, i, 1);
109     for(int i = 1; i <= m; i++)
110         g.addDoubleEdge(i + n, t, 1);
111     return true;
112 }
113 
114 boolean *visited;
115 int* divs;
116 queue<int> que;
117 
118 inline boolean getDivs(){
119     memset(visited, false, sizeof(boolean) * (t + 1));
120     divs[0] = 1;
121     visited[0] = true;
122     que.push(0);
123     while(!que.empty()){
124         int e = que.front();
125         que.pop();
126         for(int i = m_begin(g, e); i != 0; i = g[i].next){
127             int& eu = g[i].end;
128             if(!visited[eu] && g[i].flow < g[i].cap){
129                 divs[eu] = divs[e] + 1;
130                 visited[eu] = true;
131                 que.push(eu);
132             }
133         }
134     }
135     return visited[t];
136 }
137 
138 int blockedflow(int node, int minf){
139     if(node == t || minf == 0)    return minf;
140     int f, flow = 0;
141     for(int i = m_begin(g, node); i != 0; i = m_next(g, i)){
142         int& e = g[i].end;
143         if(divs[e] == divs[node] + 1 && visited[e] && (f = blockedflow(e, min(minf, g[i].cap - g[i].flow))) > 0){
144             flow += f;
145             g[i].flow += f;
146             g[g.reverse(i)].flow -= f;
147             minf -= f;
148             if(minf == 0)    return flow;
149         }
150     }
151     return flow;
152 }
153 
154 inline int maxflow(){
155     visited = new boolean[(const int)(t + 1)];
156     divs = new int[(const int)(t + 1)];
157     int res = 0;
158     while(getDivs()){
159         res += blockedflow(0, INF); 
160     }
161     return res;
162 }
163 
164 inline void solve(){
165     int res = maxflow();
166     cout << res << endl;
167 }
168 
169 inline void clear(){
170     delete[] visited;
171     delete[] divs;
172     g.clear();
173 }
174 
175 int main(){
176     while(init()){
177         solve();
178         clear();
179     }
180     return 0;
181 }

 

以上是关于[题解]poj 1274 The Perfect Stall(网络流)的主要内容,如果未能解决你的问题,请参考以下文章

The Perfect Stall 题解

POJ - 1274 The Perfect Stall

POJ 1274 - The Perfect Stall

Poj-1274-The Perfect Stall-匈牙利算法

POJ 1274 The Perfect StallHDU 2063 过山车(最大流做二分匹配)

POJ1274 The Perfect Stall 二分图,匈牙利算法