• poj2289 Jamie's Contact Groups


    思路:

    二分+最大流。
    实现:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <limits.h>
      4 #include <string.h>
      5 #include <assert.h>
      6 #include <queue>
      7 #include <vector>
      8 #include <algorithm>
      9 #include <iostream>
     10 #include <sstream>
     11 
     12 #define N (1500 + 2)
     13 #define M (N * N + 4 * N)
     14 
     15 typedef long long LL;
     16 
     17 using namespace std;
     18 
     19 struct edge 
     20 {
     21     int v, cap, next;
     22 };
     23 edge e[M];
     24 
     25 int head[N], level[N], cur[N];
     26 int num_of_edges;
     27 
     28 /*
     29  * When there are multiple test sets, you need to re-initialize before each
     30  */
     31 void dinic_init(void) 
     32 {
     33     num_of_edges = 0;
     34     memset(head, -1, sizeof(head));
     35     return;
     36 }
     37 
     38 int add_edge(int u, int v, int c1, int c2) 
     39 {
     40     int& i = num_of_edges;
     41 
     42     assert(c1 >= 0 && c2 >= 0 && c1 + c2 >= 0); // check for possibility of overflow
     43     e[i].v = v;
     44     e[i].cap = c1;
     45     e[i].next = head[u];
     46     head[u] = i++;
     47 
     48     e[i].v = u;
     49     e[i].cap = c2;
     50     e[i].next = head[v];
     51     head[v] = i++;
     52     return i;
     53 }
     54 
     55 void print_graph(int n) 
     56 {
     57     for (int u = 0; u < n; u++) 
     58     {
     59         printf("%d: ", u);
     60         for (int i = head[u]; i >= 0; i = e[i].next) 
     61         {
     62             printf("%d(%d)", e[i].v, e[i].cap);
     63         }
     64         printf("
    ");
     65     }
     66     return;
     67 }
     68 
     69 /*
     70  * Find all augmentation paths in the current level graph
     71  * This is the recursive version
     72  */
     73 int dfs(int u, int t, int bn) 
     74 {
     75     if (u == t) return bn;
     76     int left = bn;
     77     for (int &i = cur[u]; i >= 0; i = e[i].next) 
     78     {
     79         int v = e[i].v;
     80         int c = e[i].cap;
     81         if (c > 0 && level[u] + 1 == level[v]) 
     82         {
     83             int flow = dfs(v, t, min(left, c));
     84             if (flow > 0) 
     85             {
     86                 e[i].cap -= flow;
     87                 e[i ^ 1].cap += flow;
     88                 cur[u] = i;
     89                 left -= flow;
     90                 if (!left) break;
     91             }
     92         }
     93     }
     94     if (left > 0) level[u] = 0;
     95     return bn - left;
     96 }
     97 
     98 bool bfs(int s, int t) 
     99 {
    100     memset(level, 0, sizeof(level));
    101     level[s] = 1;
    102     queue<int> q;
    103     q.push(s);
    104     while (!q.empty()) 
    105     {
    106         int u = q.front();
    107         q.pop();
    108         if (u == t) return true;
    109         for (int i = head[u]; i >= 0; i = e[i].next) 
    110         {
    111             int v = e[i].v;
    112             if (!level[v] && e[i].cap > 0) 
    113             {
    114                 level[v] = level[u] + 1;
    115                 q.push(v);
    116             }
    117         }
    118     }
    119     return false;
    120 }
    121 
    122 LL dinic(int s, int t) 
    123 {
    124     LL max_flow = 0;
    125 
    126     while (bfs(s, t)) 
    127     {
    128         memcpy(cur, head, sizeof(head));
    129         max_flow += dfs(s, t, INT_MAX);
    130     }
    131     return max_flow;
    132 }
    133 
    134 vector<int> v[N];
    135 int n, m;
    136 bool check(int x)
    137 {
    138     dinic_init();
    139     for (int i = 1; i <= n; i++)
    140     {
    141         for (int j = 0; j < v[i].size(); j++)
    142         {
    143             add_edge(i, v[i][j] + n + 1, 1, 0);
    144         }
    145     }
    146     for (int i = 1; i <= n; i++)
    147         add_edge(0, i, 1, 0);
    148     for (int j = n + 1; j <= n + m; j++)
    149     {
    150         add_edge(j, n + m + 1, x, 0);
    151     }
    152     return dinic(0, n + m + 1) == n;
    153 }
    154 
    155 int main() 
    156 {
    157     while (cin >> n >> m, n || m)
    158     {
    159         getchar();
    160         string s, name;
    161         int group;
    162         for (int i = 1; i <= n; i++) v[i].clear();
    163         for (int i = 1; i <= n; i++)
    164         {
    165             getline(cin, s);
    166             stringstream ss(s);
    167             ss >> name;
    168             while (ss >> group)
    169             {
    170                 v[i].push_back(group);
    171             }
    172         }
    173         int l = 0, r = n, ans = n;
    174         while (l <= r)
    175         {
    176             int m = (l + r) >> 1;
    177             if (check(m))
    178             {
    179                 r = m - 1; ans = m;
    180             }
    181             else l = m + 1;
    182         }
    183         cout << ans << endl;
    184     }
    185     return 0;
    186 }
  • 相关阅读:
    SQL Server 快速大数据排序方法
    RGB颜色名称与色值对应表
    Visual Studio 2017 Android 调试无法连接到虚拟机
    sqlite 使用 cte 及 递归的实现示例
    C# 判断文件编码
    SQL点点滴滴_SQL分页查询
    SQL点点滴滴_判断字段或者字符中是否包含有特殊字符
    SQL点点滴滴_公用表表达式(CTE)递归的生成帮助数据
    【Oracle】Update方法
    SQL点点滴滴_DELETE小计
  • 原文地址:https://www.cnblogs.com/wangyiming/p/8214471.html
Copyright © 2020-2023  润新知