首页 > 代码库 > [题解]poj 1274 The Perfect Stall(网络流)

[题解]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(网络流)