zoukankan      html  css  js  c++  java
  • POJ 3281:Dining(最大流)

    http://poj.org/problem?id=3281

    题意:有n头牛,f种食物,d种饮料,每头牛有fnum种喜欢的食物,dnum种喜欢的饮料,每种食物如果给一头牛吃了,那么另一个牛就不能吃这种食物了,饮料也同理,问最多有多少头牛可以吃到它喜欢的饮料和食物。

    思路:一开始还以为二分匹配可以做,当然如果只有食物或者饮料其中一种就可以做。难点在于建图。看了下书,因为要保证经过牛的流量是1(每种食物对应分配给一头牛,每种饮料对应分配给一头牛,避免一头牛吃多份),所以要把牛拆成两个点。形成这样的路径S->f->cow1->cow2->d->T。

    算法思想大概是通过BFS构造出分层图,然后通过DFS找增广路更新边流量和最大流的信息。

    转的图。

     2 #include <cstring>
     3 #include <vector>
     4 #include <queue>
     5 using namespace std;
     6 #define N 410
     7 #define INF 0x3f3f3f3f
     8 struct Edge {
     9     int u, v, cap;
    10     Edge () {}
    11     Edge (int u, int v, int cap) : u(u), v(v), cap(cap) {}
    12 }edge[N*N];
    13 vector<int> G[N];
    14 int tot, S, T, dis[N], cur[N];
    15 
    16 void AddEdge(int u, int v, int c) {
    17     G[u].push_back(tot);
    18     edge[tot++] = Edge(u, v, c);
    19     G[v].push_back(tot);
    20     edge[tot++] = Edge(v, u, 0); // 反向弧的流量是0
    21 }
    22 
    23 int BFS() {
    24     queue<int> que;
    25     que.push(S);
    26     memset(dis, INF, sizeof(dis));
    27     dis[S] = 0;
    28     while(!que.empty()) {
    29         int u = que.front(); que.pop();
    30         for(int i = 0; i < G[u].size(); i++) {
    31             Edge &e = edge[G[u][i]];
    32             if(e.cap > 0 && dis[e.v] == INF) {
    33                 dis[e.v] = dis[u] + 1;
    34                 que.push(e.v);
    35             }
    36         }
    37     }
    38     return dis[T] < INF;
    39 }
    40 
    41 int DFS(int u, int maxflow) {
    42     if(u == T) return maxflow;
    43     for(int i = cur[u]; i < G[u].size(); i++) {
    44         cur[u] = i;
    45         Edge &e = edge[G[u][i]];
    46         if(dis[e.v] == dis[u] + 1 && e.cap > 0) {
    47             int flow = DFS(e.v, min(maxflow, e.cap));
    48             if(flow) {
    49                 e.cap -= flow;
    50                 edge[G[u][i]^1].cap += flow;
    51                 return flow;
    52             }
    53         }
    54     }
    55     return 0;
    56 }
    57 
    58 int Dinic() {
    59     int ans = 0, flow;
    60     while(BFS()) {
    61 //        puts("BFS");
    62         memset(cur, 0, sizeof(cur));
    63         while(flow = DFS(S, INF)) ans += flow;
    64     }
    65     return ans;
    66 }
    67 
    68 int main() {
    69     int n, f, d;
    70     while(~scanf("%d%d%d", &n, &f, &d)) {
    71         S = 0, T = 2 * n + f + d + 1, tot = 0;
    72         for(int i = 0; i <= T; i++) G[i].clear();
    73         for(int i = 1; i <= f; i++)
    74             AddEdge(S, 2 * n + i, 1); // 源点到食物
    75         for(int i = 1; i <= d; i++)
    76             AddEdge(2 * n + f + i, T, 1); // 饮料到汇点
    77         for(int i = 1; i <= n; i++) {
    78             int fnum, dnum;
    79             scanf("%d%d", &fnum, &dnum);
    80             AddEdge(i, n + i, 1); // 每只牛拆点
    81             for(int j = 1; j <= fnum; j++) {
    82                 int v; scanf("%d", &v);
    83                 AddEdge(2 * n + v, i, 1); // 食物到牛的第一个点
    84             }
    85             for(int j = 1; j <= dnum; j++) {
    86                 int v; scanf("%d", &v);
    87                 AddEdge(n + i, 2 * n + f + v, 1); // 牛的第二个点到饮料
    88             }
    89         }
    90         int ans = Dinic();
    91         printf("%d
    ", ans);
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    【数组】Unique Paths II
    【数组】Unique Paths
    【数组】word search
    购物网站布局实战
    Javascript显示和隐式类型转换
    JS检测数据类型
    从setTimeout谈js运行机制
    0.1 + 0.2 = 0.30000000000000004怎样理解
    (译)详解javascript立即执行函数表达式(IIFE)
    Redis
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6206144.html
Copyright © 2011-2022 走看看