• POJ 2289 Jamie's Contact Groups & POJ3189 Steady Cow Assignment


    这两道题目都是多重二分匹配+枚举的做法,或者可以用网络流,实际上二分匹配也就实质是网络流,通过枚举区间,然后建立相应的图,判断该区间是否符合要求,并进一步缩小范围,直到求出解。不同之处在对是否满足条件的判断,可以求最大流或者最大匹配看匹配数目是否满足题意。

    POJ 2289:

    多重二分匹配:360ms

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <climits>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <vector>
     8 #include <queue>
     9 #include <algorithm>
    10 #define esp 1e-6
    11 #define pb push_back
    12 #define in  freopen("in.txt", "r", stdin);
    13 #define out freopen("out.txt", "w", stdout);
    14 #define print(a) printf("%d
    ",(a));
    15 #define bug puts("********))))))");
    16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
    17 #define inf 0x0f0f0f0f
    18 using namespace std;
    19 typedef long long  LL;
    20 typedef vector<int> VI;
    21 typedef vector<int>:: iterator IT;
    22 #define N 1111
    23 #define M 555
    24 int n, m;
    25 bool use[M];
    26 int link[M][N], cap[M];
    27 VI g[N];
    28 bool dfs(int x)
    29 {
    30     int t;
    31     for(int i = 0; i < (int)g[x].size(); i++)
    32         if(!use[t = g[x][i]])
    33         {
    34             use[t] = true;
    35              if(link[t][0] < cap[t])
    36                 return link[t][++link[t][0]] = x, true;
    37             else
    38             {
    39                 for(int j = 1; j <= cap[t]; j++)
    40                 {
    41 //                    use[t] = true;
    42                     if(dfs(link[t][j]))
    43                         return link[t][j] = x, true;
    44                 }
    45             }
    46         }
    47     return false;
    48 }
    49 bool match(void)
    50 {
    51     memset(link, 0, sizeof(link));
    52     for(int i = 1; i <= n; i++)
    53     {
    54         memset(use, 0, sizeof(use));
    55         if(!dfs(i))
    56             return false;
    57     }
    58     return true;
    59 }
    60 void update(int mid)
    61 {
    62     for(int i = 1; i <= m; i++)
    63         cap[i] = mid;
    64 }
    65 int main(void)
    66 {
    67     while(scanf("%d%d", &n, &m), n)
    68     {
    69 //        for(int i = 1; i )
    70         char ch;
    71         for(int i = 1; i <= n; i++)
    72         {
    73             g[i].clear();
    74             scanf("%*s%c", &ch);
    75             while(ch != '
    ')
    76             {
    77                 int k;
    78                 scanf("%d%c", &k, &ch);
    79                 g[i].pb(k+1);
    80             }
    81         }
    82         int l = 1, r = n, mid;
    83         int ans = n;
    84         while(l <= r)
    85         {
    86             mid = (l+r)>> 1;
    87             update(mid);
    88             if(match())
    89             {
    90                 ans = min(mid, ans);
    91                 r = mid-1;
    92             }
    93             else l = mid+1;
    94         }
    95         printf("%d
    ", ans);
    96     }
    97     return 0;
    98 }

    网络流:589ms

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <climits>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cmath>
      7 #include <vector>
      8 #include <queue>
      9 #include <algorithm>
     10 #define esp 1e-6
     11 #define pb push_back
     12 #define in  freopen("in.txt", "r", stdin);
     13 #define out freopen("out.txt", "w", stdout);
     14 #define print(a) printf("%d
    ",(a));
     15 #define bug puts("********))))))");
     16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
     17 #define inf 0x0f0f0f0f
     18 using namespace std;
     19 typedef long long  LL;
     20 typedef vector<int> VI;
     21 typedef vector<int>:: iterator IT;
     22 #define N 5000
     23 #define M 600000
     24 struct EDGE
     25 {
     26     int i, c;
     27     EDGE *next, *ani;
     28 } *Edge[N], E[M << 1], BE[M << 1], *tag[N];
     29 int Dfn[N], Now[N], cnt;
     30 int n, m, src, sink, ndot;
     31 
     32 void init(void)
     33 {
     34     cnt = 0;
     35     memset(Edge, 0, sizeof(Edge));
     36     src = 0, sink = 1;
     37     ndot = 2*n+2*m+2;
     38 }
     39 void add(int i, int j, int c, EDGE &e1, EDGE  &e2)
     40 {
     41     e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
     42     e2.i = i, e2.c = 0, e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
     43     BE[cnt] = E[cnt], BE[cnt + 1] = E[cnt + 1];
     44     cnt += 2;
     45 }
     46 int ISAP(int s, int end, int flow)
     47 {
     48     if(s == end)
     49         return flow;
     50     int i, now = 0, vary, tab = ndot - 1;
     51     for(EDGE *p = Edge[s]; p && flow; p = p->next)
     52         if(p->c)
     53         {
     54 //            bug
     55             if(Dfn[s] == Dfn[i = p->i] + 1)
     56                 vary = ISAP(i, end, min(p->c, flow)),
     57                 p->c -= vary, p->ani->c += vary, now += vary, flow -= vary;
     58             if(p->c)
     59                 tab = min(tab, Dfn[i]);
     60             if(Dfn[src] == ndot)
     61                 return now;
     62         }
     63     if(now == 0)
     64     {
     65         if(--Now[Dfn[s]] == 0)
     66             Dfn[src] = ndot;
     67         Now[Dfn[s] = tab +1]++;
     68     }
     69 //    print(now);
     70     return now;
     71 }
     72 int max_flow(int s, int end)
     73 {
     74     memset(Dfn, 0, sizeof(Dfn));
     75     memset(Now, 0, sizeof(Now));
     76     Now[0] = ndot;
     77     int ret = 0;
     78     for(; Dfn[s] < ndot;)
     79     {
     80         ret += ISAP(s, end, inf);
     81     }
     82     return ret;
     83 }
     84 void Restore(void)
     85 {
     86     for(int i = 0; i < cnt; i++)
     87         E[i] = BE[i];
     88 }
     89 void update(int c)
     90 {
     91     Restore();
     92     for(int i = n+1; i <= n+m; i++)
     93     {
     94         tag[2*i]->c = c;
     95     }
     96 }
     97 int main(void)
     98 {
     99     while(scanf("%d%d", &n, &m), n)
    100     {
    101 
    102         char ch;
    103         init();
    104         for(int i = 1; i <= n; i++)
    105         {
    106             scanf("%*s%c", &ch);
    107             while(ch != '
    ')
    108             {
    109                 int k;
    110                 scanf("%d%c", &k, &ch);
    111                 k += n+1;
    112                 add(2*i^1, 2*k, 1, E[cnt], E[cnt + 1]);
    113             }
    114             add(2*i, 2*i^1, 1, E[cnt], E[cnt + 1]);
    115             add(src, 2*i, 1, E[cnt], E[cnt + 1]);
    116         }
    117         for(int i = 1; i <= m; i++)
    118         {
    119             add(2*(i+n), 2*(i+n)^1, inf, E[cnt], E[cnt + 1]);
    120             tag[2*(i+n)] = &E[cnt];
    121             add(2*(i+n)^1, sink, inf, E[cnt], E[cnt + 1]);
    122         }
    123         int l = 1, r = n, mid;
    124         int ans = n;
    125         while(l <= r)
    126         {
    127             mid = (l+r)>> 1;
    128             update(mid);
    129             if(max_flow(src, sink) == n)
    130             {
    131 //                bug
    132                 ans = min(mid, ans);
    133                 r = mid-1;
    134             }
    135             else l = mid+1;
    136         }
    137         printf("%d
    ", ans);
    138     }
    139     return 0;
    140 }

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    POJ 3189:

    多重二分匹配:32ms

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <climits>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <vector>
     8 #include <queue>
     9 #include <algorithm>
    10 #define esp 1e-6
    11 #define pb push_back
    12 #define in  freopen("in.txt", "r", stdin);
    13 #define out freopen("out.txt", "w", stdout);
    14 #define print(a) printf("%d
    ",(a));
    15 #define bug puts("********))))))");
    16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
    17 #define inf 0x3f3f3f3f
    18 using namespace std;
    19 typedef long long  LL;
    20 typedef vector<int> VI;
    21 typedef vector<int>:: iterator IT;
    22 #define N 30
    23 #define M 1111
    24 int n, m, mx, mi;
    25 bool use[N];
    26 int link[N][M], cap[N], rank1[M][N];
    27 bool dfs(int x)
    28 {
    29     for(int i = 1; i <= m; i++)
    30         if(rank1[x][i] >= mi && rank1[x][i] <= mx && !use[i])
    31         {
    32             use[i] = true;
    33             if(link[i][0] < cap[i])
    34                 return link[i][++link[i][0]] = x, true;
    35             else
    36                 for(int j = 1; j <= cap[i]; j++)
    37                 {
    38                     if(dfs(link[i][j]))
    39                         return link[i][j] = x, true;
    40                 }
    41         }
    42     return false;
    43 }
    44 bool match(void)
    45 {
    46     memset(link, 0, sizeof(link));
    47     for(int i = 1; i <= n; i++)
    48     {
    49         memset(use, 0, sizeof(use));
    50         if(!dfs(i))
    51             return false;
    52     }
    53     return true;
    54 }
    55 int main(void)
    56 {
    57     scanf("%d%d", &n, &m);
    58     for(int i = 1; i <= n; i++)
    59         for(int j = 1; j <= m; j++)
    60         {
    61             int x;
    62             scanf("%d", &x);
    63             rank1[i][x] = j;
    64         }
    65     for(int i = 1; i <= m; i++)
    66         scanf("%d", cap + i);
    67     int ans = m;
    68     mx = mi = 1;
    69     while(mi <= mx && mx <= m)
    70     {
    71         if(match())
    72         {
    73             ans = min(mx-mi+1, ans);
    74             mi++;
    75         }
    76         else mx++;
    77     }
    78     printf("%d
    ", ans);
    79     return 0;
    80 }

    网络流:110ms

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <climits>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cmath>
      7 #include <vector>
      8 #include <queue>
      9 #include <algorithm>
     10 #define esp 1e-6
     11 #define pb push_back
     12 #define in  freopen("in.txt", "r", stdin);
     13 #define out freopen("out.txt", "w", stdout);
     14 #define print(a) printf("%d
    ",(a));
     15 #define bug puts("********))))))");
     16 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
     17 #define inf 0x3f3f3f3f
     18 using namespace std;
     19 typedef long long  LL;
     20 typedef vector<int> VI;
     21 typedef vector<int>:: iterator IT;
     22 #define N 3000
     23 #define M 50000
     24 
     25 struct EDGE
     26 {
     27     int i, c;
     28     EDGE *next, *ani;
     29 } *Edge[N], E[M << 1], BE[M << 1];
     30 int n, m, mx, mi, src, sink, cnt, ndot;
     31 int cap[N], rank1[M][N], vis[N], dfn[N], Now[N];
     32 
     33 void add(int i, int j, int c, EDGE &e1, EDGE &e2)
     34 {
     35     e1.i = j, e1.c = c, e1.next = Edge[i], e1.ani = &e2, Edge[i] = &e1;
     36     e2.i = i, e2.c = 0, e2.next = Edge[j], e2.ani = &e1, Edge[j] = &e2;
     37     BE[cnt] = E[cnt], BE[cnt + 1] = E[cnt + 1];
     38     cnt += 2;
     39 }
     40 void init(void)
     41 {
     42     cnt = 0;
     43     memset(Edge, 0, sizeof(Edge));
     44     src = 0, sink = 1;
     45     ndot = 2*n+2*m+2;
     46 }
     47 void update(void)
     48 {
     49     for(int i = 0; i < cnt; i++)
     50         E[i] = BE[i];
     51     for(int i = 1; i <= n; i++)
     52     {
     53         int u, v;
     54         for(EDGE *p = Edge[2*i^1]; p; p = p->next)
     55         {
     56             u = i, v = p->i/2 - n;
     57             if(rank1[u][v] >= mi && rank1[u][v] <= mx)
     58                 p->c = 1;
     59             else p->c = 0;
     60         }
     61     }
     62 }
     63 void bfs(void)
     64 {
     65     queue<int> q;
     66     q.push(sink);
     67     vis[sink] = 1;
     68     Now[0] = 1;
     69     while(!q.empty())
     70     {
     71         int u = q.front();
     72         int v;
     73         q.pop();
     74         for(EDGE *p = Edge[u]; p; p = p->next)
     75             if(!vis[v = p->i] && p->ani->c)
     76             {
     77                 vis[v] = 1;
     78                 dfn[v] = dfn[u] + 1;
     79                 Now[dfn[v]]++;
     80                 q.push(v);
     81             }
     82     }
     83 }
     84 int ISAP(int s, int end, int flow)
     85 {
     86     if(s == end)
     87         return flow;
     88     int i, tab = ndot -1, now = 0, vary;
     89     for(EDGE *p = Edge[s]; p && flow; p = p->next)
     90         if(p->c)
     91         {
     92             if(dfn[s] == dfn[i = p->i] + 1)
     93                 vary = ISAP(i, end, min(flow, p->c)),
     94                 p->c -= vary, p->ani->c += vary, now +=vary, flow -= vary;
     95             if(p->c)
     96                 tab =  min(tab, dfn[i]);
     97             if(dfn[src] == ndot)
     98                 return now;
     99         }
    100     if(now == 0)
    101     {
    102         if(--Now[dfn[s]] == 0)
    103             dfn[src] = ndot;
    104         ++Now[dfn[s] = tab + 1];
    105     }
    106     return now;
    107 }
    108 int max_flow(int s, int end)
    109 {
    110     int ret = 0;
    111     memset(Now, 0, sizeof(Now));
    112     memset(dfn, 0, sizeof(dfn));
    113 //    bfs();
    114     Now[0] = ndot;
    115     for(; dfn[s] < ndot;)
    116         ret += ISAP(s, end, inf);
    117     return ret;
    118 }
    119 int main(void)
    120 {
    121     
    122     scanf("%d%d", &n, &m);
    123     init();
    124     for(int i = 1; i <= n; i++)
    125     {
    126         for(int j = 1; j <= m; j++)
    127         {
    128             int x;
    129             scanf("%d", &x);
    130             rank1[i][x] = j;
    131             add(2*i^1, 2*(j+n), 1, E[cnt], E[cnt + 1]);
    132         }
    133         add(src, 2*i, inf, E[cnt], E[cnt + 1]);
    134         add(2*i, 2*i^1, 1, E[cnt], E[cnt + 1]);
    135     }
    136     for(int i = 1; i <= m; i++)
    137     {
    138         scanf("%d", cap + i);
    139         add(2*(i+n), 2*(i+n)^1, cap[i], E[cnt], E[cnt + 1]);
    140         add(2*(i+n)^1, sink, inf, E[cnt], E[cnt + 1]);
    141     }
    142     int l = 1, r = m, mid;
    143 //    mx =m, mi = 1;
    144 
    145     int ans = m;
    146     while(l <= r)
    147     {
    148         mid = (l + r)>>1;
    149         int flag = 0;
    150         for(mi = 1, mx = mid; mx <= m; mx++, mi++)
    151         {
    152             update();
    153             if(max_flow(src, sink) == n)
    154             {
    155                 int  temp = mid;
    156                 ans = min(temp, ans);
    157                 flag = 1;
    158                 break;
    159             }
    160         }
    161         if(flag)
    162             r = mid-1;
    163         else l = mid +1 ;
    164 
    165     }
    166     printf("%d
    ", ans);
    167     return 0;
    168 }
  • 相关阅读:
    [SQL Server]分页功能的实现
    [Others]每个文件夹都具有的特殊文件夹
    [ASP.NET]使页面的大小适合打印尺寸
    [SQL Server]树形结构的创建
    [ASP.NET]获取用户控件对象的引用
    [SQL Server]关于15517号错误的一点想法
    [SQL Server]创建自定义聚合函数值得注意的问题
    Java开源BI商业智能工具
    电子商务网站搜索架构方案
    产品经理如何培养对市场的敏感度和洞察力?
  • 原文地址:https://www.cnblogs.com/rootial/p/3313665.html
Copyright © 2020-2023  润新知