[题解]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 }
时间: 2024-08-08 01:18:59

[题解]poj 1274 The Perfect Stall(网络流)的相关文章

POJ 1274 The Perfect Stall (网络流-最大流)

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18308   Accepted: 8328 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

poj 1274 The Perfect Stall 解题报告

题目链接:http://poj.org/problem?id=1274 题目意思:有 n 头牛,m个stall,每头牛有它钟爱的一些stall,也就是几头牛有可能会钟爱同一个stall,问牛与 stall 最大匹配数是多少. 二分图匹配,匈牙利算法入门题,留个纪念吧. 书上看到的一些比较有用的知识: 增广:通俗地说,设当前二分图中,已有 x 个匹配边(代码中match[i] 不为0的个数有x个),现在对 i 点(也就是代码中dfs中的参数 x) 指定一个匹配点 j, 由于 j 可能有匹配点设为

poj 1274 The Perfect Stall (二分匹配)

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17768   Accepted: 8104 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

POJ 1274 The Perfect Stall【二分图最大匹配】

题意:二分图最大匹配 分析:二分图最大匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 205; 8 int n; 9 10 int Link[maxn]; 11 int vis[maxn]; 12 vector<int> G[ma

POJ 1274 The Perfect Stall 水二分匹配

题目链接:点击打开链接 嘿嘿 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<queue> #include<functional> #define N 2011 using namespace std; int lef[N], pn;//lef[v]表示Y集的点v 当前连接

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

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24081   Accepted: 10695 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering p

poj 1274 The Perfect Stall【匈牙利算法模板题】

The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20874   Accepted: 9421 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering pr

POJ 1274 The Perfect Stall(二分匹配 最大匹配数)

题目链接:http://poj.org/problem?id=1274 Description Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the firs

POJ - 1274 The Perfect Stall 二分图 最大匹配

题目大意:有n头牛,m个牛舍,每个牛舍只能装一头牛.给出每头牛可在的牛舍序号,问最多能有多少头牛能分配到牛舍 解题思路:二分图求最大匹配,牛和牛舍分成两个点集进行匹配 #include<cstdio> #include<vector> #include<cstring> using namespace std; const int N = 210; vector<int> cow[N]; int vis[N], link[N]; int n, m; void