poj3281Dining网络流-最大流

来源:互联网 发布:专业数据库恢复 编辑:程序博客网 时间:2024/05/21 09:09

就向之前那篇博客写得一样,这里就是需要拆点的.把每头牛拆成:

饮料->牛->牛->食物.

想像一下,这样的话,如果有流量经过这条路线,就一定可以让这段流量同时经过牛-食物-饮料三件套.就可以保证解的正确性了~~~

Memory: 1580K Time: 47MS


用dinic写的.如果用其它算法(EK,sap,isap,FF都以),只是建图这里保证搞清楚 就好了.当然我们只是保证解的正确性,那你要问,我搞成食物->牛->牛->饮料可以不?当然是可以的!

好了,就这样了.

对了如果还不清楚,看我2小时前写得那篇总结.里面有关于拆点的说明,还有这种问题要加的"炒鸡源点"和"炒鸡汇点"这两个特殊点.

#include <cstdio>#include <cstring>#include <climits>#include <algorithm>#include <queue>using namespace std;const int MAX_V = 512;const int INF = INT_MAX>>1;int G[MAX_V][MAX_V];int level[MAX_V];int n, f, d, all;bool bfs(int s, int t) {memset(level, -1, sizeof(level));queue<int> Q; int p;level[s] = 0;Q.push(s);while (!Q.empty()) {p = Q.front(); Q.pop();for (int i = 0; i < all; ++i) {if (G[p][i] > 0 && level[i] < 0) {level[i] = level[p] + 1;Q.push(i);if (i == t) return true;}}}return false;}int dfs(int s, int t, int flow) {if (s == t) return flow;int res = 0, tmp;for (int i = 0; i < all; ++i) {if (G[s][i] > 0 && level[i] == level[s] + 1) {tmp = dfs(i, t, min(flow, G[s][i]));G[s][i] -= tmp;G[i][s] += tmp;res += tmp; flow -= tmp;}}return res;}int dinic(int s, int t) {int flow = 0;while (bfs(s, t)) flow += dfs(s, t, INF);return flow;}int main() {while (~scanf(" %d %d %d", &n, &f, &d)) {memset(G, 0, sizeof(G));/* 0炒鸡源点,1~f食物,f+1~f+n牛B,f+n+1~f+2*n牛屌,(牛要拆点 * f+2*n+1~f+2*n+d饮料,f+2*n+d+1炒鸡汇点 */all = f+(n<<1)+d+2;for (int i = 1; i <= f; ++i) G[0][i] = 1;for (int i = f+(n<<1)+1; i < all; ++i) G[i][all-1] = 1;int cf, cd, val; //cow's food, cow's drink, value of anyone of themfor (int i = 1; i <= n; ++i) {scanf(" %d %d", &cf, &cd);for (int j = 1; j <= cf; ++j) {scanf(" %d", &val);G[val][i+f] = 1;}//食物和牛逼连起来G[i+f][i+f+n] = 1; //牛逼和牛屌连以来for (int j = 1; j <= cd; ++j) {scanf(" %d", &val);G[i+f+n][f+(n<<1)+val] = 1;}//牛屌和饮料连起来}printf("%d\n", dinic(0, all-1));}return 0;}

呃,至于邻接矩阵被吐槽,是因为我智力有限,觉得这玩意方便....链表之后补学一下..........

0 0