zoukankan      html  css  js  c++  java
  • UVA10779 Collectors Problem

    题目链接:https://cn.vjudge.net/problem/UVA-10779

    前言:

      本题是关于姜志豪《网络流的一些建模方法》的笔记。

    知识点:  最大流

    题意摘抄:

      (Bob) 和他的朋友从糖果包装里收集贴纸。(Bob) 和他的朋友总共 (n) 人。共有 (m) 种不同的贴纸。

      每人手里都有一些(可能有重复的)贴纸,并且只跟别人交换他所没有的贴纸。贴纸总是一对一交换。

      (Bob) 比这些朋友更聪明,因为他意识到只跟别人交换自己没有的贴纸并不总是最优的。在某些情况下,换来一张重复贴纸更划算。

      假设 (Bob) 的朋友只和 (Bob) 交换(他们之间不交换),并且这些朋友只会出让手里的重复贴纸来交换他们没有的不同贴纸。你的任务是帮助 (Bob) 算出他最终可以得到的不同贴纸的最大数量。

      ((2 le n le 10, 5 le m le 25))

    解题思路:

      每种贴纸、每个朋友都各视为一个点,再加上一个源点和一个汇点。

      对于每种贴纸,建一条从源点到这种贴纸的边,容量为 (Bob) 所拥有的这种贴纸的张数;

      对于每一个朋友,如果他没有某种贴纸,就建一条从这种贴纸到他的边,容量为 (1);如果他有这种贴纸并且拥有量 (k) 大于(1) ,则建一条从他到这种贴纸的边,容量为 (k-1).

      对于每种贴纸,再建一条边到汇点,容量为 (1).

    AC代码:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int MAXN = 510;//点数的最大值
      4 const int MAXM = 15000;//边数的最大值
      5 const int INF = 0x3f3f3f3f;
      6 
      7 struct Edge{
      8     int to,next,cap,flow;
      9 }edge[MAXM];//注意是MAXM
     10 int tol;
     11 int head[MAXN];
     12 int gap[MAXN],dep[MAXN],cur[MAXN];
     13 void init(){
     14     tol = 0;
     15     memset(head,-1,sizeof(head));
     16 }
     17 void addedge(int u,int v,int w,int rw = 0){
     18     edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0;
     19     edge[tol].next = head[u]; head[u] = tol++;
     20     edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0;
     21     edge[tol].next = head[v]; head[v] = tol++;
     22 }
     23 int Q[MAXN];
     24 void BFS(int start,int end){
     25     memset(dep,-1,sizeof(dep));
     26     memset(gap,0,sizeof(gap));
     27     gap[0] = 1;
     28     int front = 0, rear = 0;
     29     dep[end] = 0;
     30     Q[rear++] = end;
     31     while(front != rear){
     32         int u = Q[front++];
     33         for(int i = head[u]; i != -1; i = edge[i].next){
     34             int v = edge[i].to;
     35             if(dep[v] != -1)
     36                 continue;
     37             Q[rear++] = v;
     38             dep[v] = dep[u] + 1;
     39             gap[dep[v]]++;
     40         }
     41     }
     42 }
     43 int S[MAXN];
     44 int sap(int start,int end,int N){
     45     BFS(start,end);
     46     memcpy(cur,head,sizeof(head));
     47     int top = 0;
     48     int u = start;
     49     int ans = 0;
     50     while(dep[start] < N){
     51         if(u == end){
     52             int Min = INF;
     53             int inser;
     54             for(int i = 0;i < top;i++)
     55                 if(Min > edge[S[i]].cap - edge[S[i]].flow){
     56                     Min = edge[S[i]].cap - edge[S[i]].flow;
     57                     inser = i;
     58                 }
     59             for(int i = 0;i < top;i++){
     60                 edge[S[i]].flow += Min;
     61                 edge[S[i]^1].flow -= Min;
     62             }
     63             ans += Min;
     64             top = inser;
     65             u = edge[S[top]^1].to;
     66             continue;
     67         }
     68         bool flag = false;
     69         int v;
     70         for(int i = cur[u]; i != -1; i = edge[i].next){
     71             v = edge[i].to;
     72             if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){
     73                 flag = true;
     74                 cur[u] = i;
     75                 break;
     76             }
     77         }
     78         if(flag){
     79             S[top++] = cur[u];
     80             u = v;
     81             continue;
     82         }
     83         int Min = N;
     84         for(int i = head[u]; i != -1; i = edge[i].next)
     85             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
     86                 Min = dep[edge[i].to];
     87                 cur[u] = i;
     88             }
     89         gap[dep[u]]--;
     90         if(!gap[dep[u]])
     91             return ans;
     92         dep[u] = Min + 1;
     93         gap[dep[u]]++;
     94         if(u != start)
     95             u = edge[S[--top]^1].to;
     96     }
     97     return ans;
     98 }
     99 int has[30];
    100 int main(){
    101     int T;
    102     int n,m,k;
    103     int num;
    104     int kase=1;
    105     scanf("%d",&T);
    106     while(T--){
    107         init();
    108         int s=0,t=MAXN-1;
    109         memset(has,0,sizeof(has));
    110         scanf("%d%d",&n,&m);
    111         scanf("%d",&k);
    112         while(k--){
    113             scanf("%d",&num);
    114             has[num]++;
    115         }
    116         for(int i=1;i<=m;i++){
    117             addedge(s,i,has[i]);
    118             addedge(i,t,1);
    119         }
    120         for(int i=1;i<n;i++){
    121             memset(has,0,sizeof(has));
    122             scanf("%d",&k);
    123             while(k--){
    124                 scanf("%d",&num);
    125                 has[num]++;
    126             }
    127             for(int j=1;j<=m;j++){
    128                 if(!has[j])
    129                     addedge(j,30+i,1);
    130                 else if(has[j]>1)
    131                     addedge(30+i,j,has[j]-1);
    132             }
    133         }
    134         printf("Case #%d: %d
    ",kase++,sap(s,t,2+m+n));
    135     }
    136     return 0;
    137 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Xamarin.Forms项目无法添加服务引用
    Xamarin Android长度单位区别
    21IC菜农研究的HotWC3超级CRC运算器
    Delphi天气预报查询
    超外差接收机工作原理?
    ARM汇编指令的特点和速查表
    序列号的设计,不重复的实现一机一码
    iOS第一个简单APP
    GetEnvironmentVariable 获取常用系统变量(转)
    Delphi版的Base64转换函数(修改版)
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9061363.html
Copyright © 2011-2022 走看看