zoukankan      html  css  js  c++  java
  • ZOJ 3642 多重匹配 离散化.cpp

    题意:

    已知一些小孩所拥有的信息和他最多共享信息量和最少共享信息量 问其中某一个小孩最多得到的信息量

    给出n表示有n个小孩

    接下来n行有 a b c a1 a2 a3 a4 ... ai   表示该小孩有信息a条 最少共享 b 条 最多共享 c 条 其中a1 a2 a3~ai为小孩拥有信息id号

    给出一个m 问的是小孩m最多得到的信息量

     

    思路:

    鉴于这道题中信息id号从 0 ~ 200 但是每个小孩最初最多知道10条信息..

    所以为了防止遍历的时候太浪费时间 应该把题目id号变成连续的..

     

    然后可以用多重匹配或者最大流来做..

    Tips:

    多重匹配的建图方法:

     以信息为 集合X  孩子为 集合Y

    然后 limit 为 Y 集合的最大容量 即孩子的最大共享量   但是孩子 m 的容量为INF

     

    最大流的建图方法:

    一个超级源点..连接孩子 除了第m个孩子之外..

    别的孩子都连线..容量为最大分享量..而第m个孩子的容量为INF 表示可以接受无穷多的信息

    然后每个孩子和对应的信息连线 容量为1

    每个信息又与超级汇点连线 容量为1

    求超级源点到超级汇点的最大流既是答案

    Code:

    最大流
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 #define clr(x) memset(x, 0xff, sizeof(x))
      6 #define min(a,b)(a)<(b)?(a):(b)
      7 
      8 const int INF = 0x1f1f1f1f;
      9 const int maxn = 410;
     10 const int maxm = 200010;
     11 
     12 struct Info
     13 {
     14     int m;
     15     int id[210];
     16     int cap;
     17 }info[210];
     18 
     19 struct Edge
     20 {
     21     int from;
     22     int to;
     23     int next;
     24     int w;
     25 }edge[maxm];
     26 int tot;
     27 int head[maxn];
     28 
     29 int num[1000010];
     30 
     31 void add(int s, int u, int f1, int f2)
     32 {
     33     edge[tot].from = s;
     34     edge[tot].to = u;
     35     edge[tot].w = f1;
     36     edge[tot].next = head[s];
     37     head[s] = tot++;
     38     edge[tot].from = u;
     39     edge[tot].to = s;
     40     edge[tot].w = f2;
     41     edge[tot].next = head[u];
     42     head[u] = tot++;
     43 }
     44 
     45 int q[maxn];
     46 int cnt[maxn];
     47 int d[maxn];
     48 int low[maxn];
     49 int cur[maxn];
     50 
     51 int maxflow(int s, int t, int n)
     52 {
     53     int *front = q, *rear = q;
     54     for(int i = 0; i <= n; ++i) {
     55         d[i] = n;
     56         cnt[i] = 0;
     57     }
     58     cnt[n] = n-1;
     59     cnt[0]++;
     60     d[t] = 0;
     61     *rear++ = t;
     62     while(front < rear) {
     63         int v = *front++;
     64         for(int i = head[v]; i != -1; i = edge[i].next) {
     65             if(d[edge[i].to] == n && edge[i^1].w > 0) {
     66                 d[edge[i].to] = d[v] + 1;
     67                 cnt[n]--;
     68                 cnt[d[edge[i].to]]++;
     69                 *rear++ = edge[i].to;
     70             }
     71         }
     72     }
     73 
     74     int flow = 0, u = s, top = 0;
     75     low[0] = INF;
     76     for(int i = 0; i <= n; ++i) {
     77         cur[i] = head[i];
     78     }
     79     while(d[s] < n) {
     80         int &i = cur[u];
     81         for(; i != -1; i = edge[i].next) {
     82             if(edge[i].w > 0 && d[u] == d[edge[i].to]+1) {
     83                 low[top+1] = min(low[top], edge[i].w);
     84                 q[++top] = i;
     85                 u = edge[i].to;
     86                 break;
     87             }
     88         }
     89         if(i != -1) {
     90             if(u == t) {
     91                 int minf = low[top];
     92                 for(int p = 1, i; p <= top; ++p) {
     93                     i = q[p];
     94                     edge[i].w -= minf;
     95                     edge[i^1].w += minf;
     96                 }
     97                 flow += minf;
     98                 u = s;
     99                 low[0] = INF;
    100                 top = 0;
    101             }
    102         }
    103         else {
    104             int old_du = d[u];
    105             cnt[old_du]--;
    106             d[u] = n-1;
    107             for(int i = head[u]; i != -1; i = edge[i].next)
    108                 if(edge[i].w > 0 && d[u] > d[edge[i].to]) {
    109                     d[u] = d[edge[i].to];
    110                 }
    111                 cnt[++d[u]]++;
    112                 if(d[u]<n)
    113                     cur[u] = head[u];
    114                 if(u != s) {
    115                     u = edge[q[top]].from;
    116                     --top;
    117                 }
    118                 if(cnt[old_du] == 0) break;
    119         }
    120     }
    121     return flow;
    122 }
    123 
    124 int main()
    125 {
    126     int i, j, k;
    127     int n, tmp, tt, m;
    128     while(scanf("%d", &n) != EOF)
    129     {
    130         clr(head), tot = 0, tt = n+1;
    131         memset(num, 0, sizeof(num));
    132 
    133         for(i = 1; i <= n; ++i) {
    134             scanf("%d%*d%d", &info[i].m, &info[i].cap);
    135             for(j = 0; j < info[i].m; ++j){
    136                 scanf("%d", &tmp);
    137                 if(num[tmp] == 0) num[tmp] = tt++;
    138                 info[i].id[j] = num[tmp];
    139             }
    140         }
    141 
    142         scanf("%d", &m);
    143 
    144         for(i = 1; i <= n; ++i) {
    145             if(i != m)
    146                 add(0, i, info[i].cap, 0);
    147             else
    148                 add(0, i, INF, 0);
    149             for(j = 0; j < info[i].m; ++j)
    150                 add(i, info[i].id[j], 1, 0);
    151         }
    152 
    153         for(i = n+1; i < tt; ++i)
    154         add(i, tt, 1, 0);
    155 
    156         int ans = maxflow(0, tt, tt+1);
    157 
    158         printf("%d\n", ans);
    159     }
    160     return 0;
    161 }

     

    多重匹配
     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define clr(x) memset(x, 0, sizeof(x))
     6 const int INF = 0x1f1f1f1f;
     7 
     8 bool G[410][210];
     9 int limit[410];
    10 bool vis[410];
    11 int v1, v2, sum;
    12 int v[410];
    13 int vv[210][410];
    14 int num[1000010];
    15 
    16 bool find(int u)
    17 {
    18     int i, j, k;
    19     for(i = 0; i < v2; ++i) {
    20         if(G[u][i] && !vis[i]) {
    21             vis[i] = true;
    22             if(v[i] < limit[i]) {
    23                 vv[i][v[i]++] = u;
    24                 return true;
    25             }
    26 
    27             for(j = 0; j < v[i]; ++j) {
    28                 if(find(vv[i][j])) {
    29                     vv[i][j] = u;
    30                     return true;
    31                 }
    32             }
    33         }
    34     }
    35     return false;
    36 }
    37 
    38 void solve()
    39 {
    40     clr(vis);
    41     sum = 0;
    42     for(int i = 1; i <= v1; ++i) {
    43         clr(vis);
    44         if(find(i)) {
    45             sum++;
    46         }
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     int i, j, k;
    53     int n, m, tmp, tt;
    54     while(scanf("%d", &n) != EOF)
    55     {
    56         clr(G), clr(num);
    57         tt = 1;
    58 
    59         for(i = 0; i < n; ++i) {
    60             scanf("%d%*d%d", &m, &limit[i]);
    61             while(m--) {
    62                 scanf("%d", &tmp);
    63                 if(num[tmp] == 0) num[tmp] = tt++;
    64                 G[num[tmp]][i] = true;
    65             }
    66         }
    67 
    68         v1 = tt-1;
    69         v2 = n;
    70         scanf("%d", &m);
    71 
    72         limit[m-1] = INF;
    73         solve();
    74 
    75         printf("%d\n", sum);
    76     }
    77     return 0;
    78 }

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4810

  • 相关阅读:
    17 python学习笔记-异常处理
    二、如何使用postman做接口测试笔记(二)
    16 python学习笔记-使用yagmail模块发送邮件
    15 python学习笔记-多进程multiprocessing
    14 python学习笔记-多线程threading
    用HTML5构建一个流程图绘制工具
    百度地图API绘制带头箭头的折线
    使用JsPlumb绘制拓扑图的通用方法
    SQL Server 2008启用sa账户
    eclipse/ggts/myeclipse清除SVN用户名和密码
  • 原文地址:https://www.cnblogs.com/Griselda/p/2697467.html
Copyright © 2011-2022 走看看