zoukankan      html  css  js  c++  java
  • tyvj P1517 飘飘乎居士的乌龟(最大流)

                              P1517 飘飘乎居士的乌龟
                        时间: 1000ms / 空间: 131072KiB / Java类名: Main

    背景

    飘飘乎居士养了乌龟。当然,这些乌龟是用来出售赚取利润的。

    描述

    飘飘乎居士的乌龟被安置在了m个窝中。现在,飘飘乎居士已经接到了n个人的定购通知,他们会按顺序在来挑选乌龟,其中,第i个人会在pi个窝中挑选乌龟, 但最多只想买xi只乌龟。另外,在第i个人购买完乌龟以后,飘飘乎居士会将指定的qi个窝中的龟进行调整,他可以任意调换指定的qi个窝中乌龟数量。飘飘 乎希望知道,在n个人购买完乌龟后,他最多可以出售多少只乌龟?

    输入格式

    输入格式:第一行,两个正整数n、m。
              接下来一行m个整数(可能为0),第i个整数表示第i个窝中乌龟的数量。

              接下来输入分为n组,每组3行输入,第i组表示第i个人的信息:
    第一行一个整数xi,表示第i个人最多购买的乌龟数量
    第二行一个整数pi以及pi整数,表示该顾客会在pi个指定的窝中挑选乌龟
    第三行一个整数qi(qi可能为0)以及跟着的qi个正整数,表示在第i个人购买完乌龟后,飘飘乎居士会调整这qi个窝中乌龟的数量。

    输出格式

    输出格式:一行,表示飘飘乎居士最多出售乌龟的数量。

    测试样例1

    输入

    输入样例1:
    2 4
    2 2 5 0
    3
    1 3
    2 1 4

    10
    2 4 3
    0

    输入样例2:
    2 4
    1 2 3 3
    3
    2 1 4
    2 4 3

    4
    1 3
    4 1 2 3 4

    输出

    输出样例1:
    7
    输出样例2:
    7

    备注

     Hint:样例一解释:飘飘乎居士4个窝,初始时,第一个窝里有2只乌龟,第二个窝里有2只乌龟,第三个窝里有5只乌龟;第四窝里没有乌龟,共有2位顾客来购买乌龟。
           在 第一位顾客到来时,他想在3号窝中挑选乌龟,最多只想买3只乌龟。飘飘乎居士将3号窝中的乌龟出售。出售以后,3号窝剩下2只乌龟,飘飘乎居士可以调整 1、4号窝中乌龟的数量,将1号窝中的2只乌龟转入4号窝中,这样,1号窝没有乌龟,3号窝2只乌龟,4号窝有2只乌龟。
    在第二个顾客来时,他想要在3 4号窝中挑选最多10只乌龟,飘飘乎居士将从1号窝调整到4号窝中的2只乌龟以及3号窝剩下的2只乌龟卖出。共卖出7只乌龟,也就是最后的答案。
      
       数据范围:0<n、m<=10
       每个窝初始时乌龟的数量以及每位顾客购买乌龟的数量<=100000
       0<=Pi、qi<=n
       数据保证输入的正确性。
     

    【思路】

           最大流。

           构图:

           1 对于每个龟窝建立n个结点,建立s t点。

           2 连边:

           (s,ui,twi)        表示龟的数量

         (ui,tmp,INF),(tmp,t,xi)             tmp为中转结点,限制pi个点的总流量

         (qj,qj+1,INF)   表示乌龟的调换

         (ui,ui+1,INF)

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<vector>
      5 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
      6 using namespace std;
      7 
      8 const int maxn = 500+10;
      9 const int INF = 1e9;
     10 
     11 struct Edge{
     12     int u,v,cap,flow;
     13 };
     14 struct Dinic {
     15     int n,m,s,t;
     16     bool vis[maxn];
     17     int d[maxn],cur[maxn];
     18     vector<int> G[maxn];
     19     vector<Edge> es;
     20     
     21     void init(int n) {
     22         this->n=n;
     23         es.clear();
     24         for(int i=0;i<n;i++) G[i].clear();
     25     }
     26     void AddEdge(int u,int v,int cap) {
     27         es.push_back((Edge){u,v,cap,0});
     28         es.push_back((Edge){v,u,0,0});
     29         m=es.size();
     30         G[u].push_back(m-2);
     31         G[v].push_back(m-1);
     32     }
     33     
     34     bool BFS() {
     35         queue<int> q;
     36         memset(vis,0,sizeof(vis));
     37         q.push(s); vis[s]=1; d[s]=0;
     38         while(!q.empty()) {
     39             int u=q.front(); q.pop();
     40             for(int i=0;i<G[u].size();i++) {
     41                 Edge& e=es[G[u][i]];
     42                 int v=e.v;
     43                 if(!vis[v] && e.cap>e.flow) {
     44                     vis[v]=1;
     45                     d[v]=d[u]+1;
     46                     q.push(v);
     47                 }
     48             }
     49         }
     50         return vis[t];
     51     }
     52     int DFS(int u,int a) {
     53         if(u==t || a==0) return a;
     54         int flow=0,f;
     55         for(int& i=cur[u];i<G[u].size();i++){
     56             Edge& e=es[G[u][i]];
     57             int v=e.v;
     58             if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
     59                 e.flow+=f;
     60                 es[G[u][i]^1].flow-=f;
     61                 flow+=f,a-=f;
     62                 if(!a) break;
     63             }
     64         }
     65         return flow;
     66     }
     67     int Maxflow(int s,int t) {
     68         this->s=s , this->t=t;
     69         int flow=0;
     70         while(BFS()) {
     71             memset(cur,0,sizeof(cur));
     72             flow+=DFS(s,INF);
     73         }
     74         return flow;
     75     }
     76 } dc;
     77 
     78 int n,m;
     79 int q[maxn];
     80 
     81 int main() {
     82     scanf("%d%d",&n,&m);  m++;
     83     dc.init(n*m+2);
     84     int s=n*m,t=s+1,x;
     85     FOR(i,0,m-1) {
     86         scanf("%d",&x);
     87         dc.AddEdge(s,i,x);
     88     }
     89     int a,b,limit;
     90     FOR(i,0,n) {
     91         scanf("%d%d",&limit,&a);
     92         int tmp=i*m+m-1;            //中转结点
     93         dc.AddEdge(tmp,t,limit);
     94         FOR(j,0,a) {
     95             scanf("%d",&b); b--;
     96             dc.AddEdge(i*m+b,tmp,INF);
     97         }
     98         scanf("%d",&a);
     99         FOR(j,0,a) scanf("%d",&q[j]),q[j]--;
    100         if(i<n-1)  FOR(j,0,a-1) {
    101             dc.AddEdge(i*m+q[j],(i+1)*m+q[j+1],INF);
    102             dc.AddEdge(i*m+q[j+1],(i+1)*m+q[j],INF);
    103         }
    104     }
    105     FOR(i,0,n-1) FOR(j,0,m-1)
    106         dc.AddEdge(i*m+j,(i+1)*m+j,INF);
    107     int flow=dc.Maxflow(s,t);
    108     printf("%d
    ",flow);
    109     return 0;
    110 }
  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5060919.html
Copyright © 2011-2022 走看看