zoukankan      html  css  js  c++  java
  • poj 1698 二分图多重匹配

    网络流解法:

    容易想到将每一天看做一个点并和汇点连容量为1的边(因为一天只能做一件事情),每个电影看做一个点并和源点连容量为d的边(即几天可以完成),然后电影和对应天数连容量为1的边,求最大流判断是否满流即可。

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 
      6 const int INF = 9999999;
      7 const int N = 400;
      8 const int M = 20000;
      9 int head[N];
     10 int level[N];
     11 int q[N];
     12 int n, e, front, rear;
     13 
     14 void init()
     15 {
     16     e = 0;
     17     memset( head, -1, sizeof(head) );
     18 }
     19 
     20 struct Edge 
     21 {
     22     int v, next, cap;
     23 } edge[M];
     24 
     25 void addEdge( int u, int v, int cap )
     26 {
     27     edge[e].v = v;
     28     edge[e].cap = cap;
     29     edge[e].next = head[u];
     30     head[u] = e++;
     31     edge[e].v = u;
     32     edge[e].cap = 0;
     33     edge[e].next = head[v];
     34     head[v] = e++;
     35 }
     36 
     37 bool bfs( int s, int t )
     38 {
     39     front = rear = 0;
     40     memset( level, -1, sizeof(level) );
     41     q[rear++] = s;
     42     level[s] = 0;
     43     while ( front < rear )
     44     {
     45         int u = q[front++];
     46         for ( int i = head[u]; i != -1; i = edge[i].next )
     47         {
     48             int v = edge[i].v, cap = edge[i].cap;
     49             if ( level[v] == -1 && cap > 0 )
     50             {
     51                 level[v] = level[u] + 1;
     52                 q[rear++] = v;
     53             }
     54         }
     55     }
     56     return level[t] != -1;
     57 }
     58 
     59 int dfs( int u, int sum, int t )
     60 {
     61     if ( u == t ) return sum;
     62     int os = 0;
     63     for ( int i = head[u]; i != -1; i = edge[i].next )
     64     {
     65         int v = edge[i].v, cap = edge[i].cap;
     66         if ( level[v] == level[u] + 1 && cap > 0 )
     67         {
     68             int tt = dfs( v, min( sum, cap ), t );
     69             if ( tt == 0 ) continue;
     70             edge[i].cap -= tt;
     71             edge[i ^ 1].cap += tt;
     72             sum -= tt;
     73             os += tt;
     74             if ( sum == 0 ) break;
     75         }
     76     }
     77     if ( os == 0 ) level[u] = -1;
     78     return os;
     79 }
     80 
     81 int dinic( int s, int t )
     82 {
     83     int res = 0;
     84     while ( bfs( s, t ) )
     85     {
     86         res += dfs( s, INF, t );
     87     }
     88     return res;
     89 }
     90 
     91 const int D = 7;
     92 int nn[D];
     93 
     94 int main ()
     95 {
     96     int _case;
     97     scanf("%d", &_case);
     98     while ( _case-- )
     99     {
    100         scanf("%d", &n);
    101         init();
    102         int tot = 0, wmax = -1, d, w;
    103         for ( int i = 1; i <= n; i++ )
    104         {
    105             for ( int j = 0; j < D; j++ )
    106             {
    107                 scanf("%d", nn + j);
    108             }
    109             scanf("%d%d", &d, &w);
    110             tot += d;
    111             wmax = max( wmax, w );
    112             addEdge( 0, i, d );
    113             for ( int j = 0; j < D; j++ )
    114             {
    115                 if ( nn[j] == 1 )
    116                 {
    117                     for ( int k = 0; k < w; k++ )
    118                     {
    119                         int num = n + k * 7 + j + 1;
    120                         addEdge( i, num, 1 );
    121                     }
    122                 }
    123             }
    124         }
    125         int tid = n + wmax * 7 + 1;
    126         for ( int i = n + 1; i < tid; i++ )
    127         {
    128             addEdge( i, tid, 1 );
    129         }
    130         if ( dinic( 0, tid ) == tot )
    131         {
    132             puts("Yes");
    133         }
    134         else
    135         {
    136             puts("No");
    137         }
    138     }
    139     return 0;
    140 }

    匈牙利解法(些许改变):

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <vector>
      5 using namespace std;
      6 
      7 const int X = 350;
      8 const int Y = 20;
      9 int head[X];
     10 int sz[Y];
     11 bool visit[Y];
     12 vector<int> mark[Y];
     13 int e;
     14 
     15 void init()
     16 {
     17     e = 0;
     18     memset( head, -1, sizeof(head) );
     19 }
     20 
     21 struct Edge 
     22 {
     23     int v, next;
     24 } edge[X * Y];
     25 
     26 void addEdge( int u, int v )
     27 {
     28     edge[e].v = v;
     29     edge[e].next = head[u];
     30     head[u] = e++;
     31 }
     32 
     33 int dfs( int u )
     34 {
     35     for ( int i = head[u]; i != -1; i = edge[i].next )
     36     {
     37         int v = edge[i].v;
     38         if ( !visit[v] )
     39         {
     40             visit[v] = 1;
     41             if ( mark[v].size() < sz[v] )
     42             {
     43                 mark[v].push_back(u);
     44                 return 1;
     45             }
     46             else
     47             {
     48                 for ( int j = 0; j < mark[v].size(); j++ )
     49                 {
     50                     if ( dfs( mark[v][j] ) )
     51                     {
     52                         mark[v][j] = u;
     53                         return 1;
     54                     }
     55                 }
     56             }
     57         }
     58     }
     59     return 0;
     60 }
     61 
     62 const int D = 7;
     63 int nn[D];
     64 
     65 int main ()
     66 {
     67     int _case;
     68     scanf("%d", &_case);
     69     while ( _case-- )
     70     {
     71         int n;
     72         scanf("%d", &n);
     73         init();
     74         int tot = 0, wmax = -1, d, w;
     75         for ( int i = 0; i < n; i++ )
     76         {
     77             for ( int j = 0; j < D; j++ )
     78             {
     79                 scanf("%d", nn + j);
     80             }
     81             scanf("%d%d", &d, &w);
     82             sz[i] = d;
     83             tot += d;
     84             wmax = max( wmax, w );
     85             for ( int j = 0; j < D; j++ )
     86             {
     87                 if ( nn[j] == 1 )
     88                 {
     89                     for ( int k = 0; k < w; k++ )
     90                     {
     91                         int num = k * 7 + j;
     92                         addEdge( num, i );
     93                     }
     94                 }
     95             }
     96         }
     97         for ( int i = 0; i < n; i++ )
     98         {
     99             mark[i].clear();
    100         }
    101         int res = 0;
    102         for ( int i = 0; i < 7 * wmax; i++ )
    103         {
    104             memset( visit, 0, sizeof(visit) );
    105             res += dfs(i);
    106         }
    107         if ( res == tot )
    108         {
    109             puts("Yes");
    110         }
    111         else
    112         {
    113             puts("No");
    114         }
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    Babelfish
    【动态规划】货币面值
    contest 1.18
    contest 1.17
    contest 1.16
    contest 1.15
    contest 1.14
    contest 1.13
    contest 12.31
    [cf]Round #529 (Div. 3)
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4750976.html
Copyright © 2011-2022 走看看