zoukankan      html  css  js  c++  java
  • Poj 3281 Dining

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

    题意:约翰给他的牛准备F种食物和D种饮料(约翰和牛,Alice和Bob……)每头牛都有自己喜欢的食物和饮料,而每种食物和饮料只能分配给一头牛。最多能有多少头牛能同时分配到喜欢的食物和饮料。

    题解:最大流的模型之一,要用到所谓的拆点。除了牛、食物和饮料之外建立s和t,把牛的数量*2,两个分配相同的牛之间连边。连边顺序:s->食物->牛->牛->饮料->t。

    注意:输入lf[][]、ld[][]时要注意t-1,因为题目数据是从1开始计数的。用小兰的话说:“好无赖啊……”。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <string>
      7 #include <vector>
      8 #include <list>
      9 #include <map>
     10 #include <queue>
     11 #include <stack>
     12 #include <bitset>
     13 #include <algorithm>
     14 #include <numeric>
     15 #include <functional>
     16 #include <set>
     17 #include <fstream>
     18 
     19 using namespace std;
     20 
     21 const int INF=100000000;
     22 const int maxn=2100;
     23 int lf[maxn][maxn],ld[maxn][maxn];
     24 struct edge{
     25     int to,cap,rev;
     26 };
     27 vector<edge> G[maxn];
     28 int level[maxn];
     29 int iter[maxn];
     30 
     31 void add_edge(int from,int to,int cap)
     32 {
     33     G[from].push_back((edge){to,cap,(int)G[to].size()});
     34     G[to].push_back((edge){from,0,(int)G[from].size()-1});
     35 }
     36 
     37 void bfs(int s)
     38 {
     39     memset(level, -1, sizeof(level));
     40     queue<int> que;
     41     level[s]=0;
     42     que.push(s);
     43     while (!que.empty()) {
     44         int v=que.front();
     45         que.pop();
     46         for (int i=0; i<G[v].size(); i++) {
     47             edge &e=G[v][i];
     48             if (e.cap>0&&level[e.to]<0) {
     49                 level[e.to]=level[v]+1;
     50                 que.push(e.to);
     51             }
     52         }
     53     }
     54 }
     55 
     56 int dfs(int v,int t,int f)
     57 {
     58     if (v==t) {
     59         return f;
     60     }
     61     for (int &i=iter[v]; i<G[v].size(); i++) {
     62         edge &e=G[v][i];
     63         if (e.cap>0 && level[v]<level[e.to]) {
     64             int d=dfs(e.to, t, min(f,e.cap));
     65             if (d>0) {
     66                 e.cap-=d;
     67                 G[e.to][e.rev].cap+=d;
     68                 return d;
     69             }
     70         }
     71     }
     72     return 0;
     73 }
     74 
     75 int max_flow(int s,int t)
     76 {
     77     int flow=0;
     78     for (;;) {
     79         bfs(s);
     80         if (level[t]<0) {
     81             return flow;
     82         }
     83         memset(iter, 0, sizeof(iter));
     84         int f;
     85         while ((f=dfs(s, t, INF))>0) {
     86             flow+=f;
     87         }
     88     }
     89 }
     90 int main()
     91 {
     92     //freopen("/Users/apple/Desktop/poj 3281/poj 3281/in", "r", stdin);
     93     //freopen("/Users/apple/Desktop/poj 3281/poj 3281/out", "w", stdout);
     94     int N,F,D;
     95     memset(lf, 0, sizeof(lf));
     96     memset(ld, 0, sizeof(ld));
     97     scanf("%d%d%d",&N,&F,&D);
     98     int fi,di,fj,dk;
     99     for (int i=0; i<N; i++) {
    100         scanf("%d%d",&fi,&di);
    101         for (int j=0; j<fi; j++) {
    102             //scanf("%d",&lf[i][j]);
    103             scanf("%d",&fj);
    104             lf[i][fj-1]=1;
    105         }
    106         for (int k=0; k<di; k++) {
    107             //scanf("%d",&ld[i][k]);
    108             scanf("%d",&dk);
    109             ld[i][dk-1]=1;
    110         }
    111     }
    112     
    113     //0~N-1食物与牛
    114     //N~N*2-1饮料与牛
    115     //N*2~N*2+F-1食物
    116     //N*2+F~N*2+F+D-1饮料
    117     int s=N*2+F+D,t=s+1;
    118     
    119     for (int i=0; i<F; i++) {
    120         add_edge(s, N*2+i, 1);
    121     }
    122     for (int i=0; i<D; i++) {
    123         add_edge(N*2+F+i, t, 1);
    124     }
    125     for (int i=0; i<N; i++) {
    126         add_edge(i, N+i, 1);
    127         for (int j=0; j<F; j++) {
    128             if (lf[i][j]) {
    129                 add_edge(N*2+j, i, 1);
    130             }
    131         }
    132         for (int k=0; k<D; k++) {
    133             if (ld[i][k]) {
    134                 add_edge(N+i, N*2+F+k, 1);
    135             }
    136         }
    137     }
    138     
    139     printf("%d
    ",max_flow(s, t));
    140     
    141     return 0;
    142 }
  • 相关阅读:
    android 各国语言对应的缩写
    Android 程式开发:(十三)特殊碎片 —— 13.2 DialogFragment
    Android Bitmap和Canvas学习笔记 [转]
    Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
    XAMPP 在windows下无法启动Apache解决方案
    深入浅出Java并发包—锁机制(一)
    深入浅出Java并发包—锁(Lock)VS同步(synchronized)
    深入浅出Java并发包—CAS机制
    深入浅出Java并发包—指令重排序
    深入浅出Java并发包—原子类操作
  • 原文地址:https://www.cnblogs.com/der-z/p/3690055.html
Copyright © 2011-2022 走看看