洛谷P1231 教辅的组成

简介: 洛谷P1231 教辅的组成

原题索引:https://www.luogu.com.cn/problem/P1231


题目背景


滚粗了的 HansBug 在收拾旧语文书,然而他发现了什么奇妙的东西。


题目描述


蒟蒻 HansBug 在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题。然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册。已知一个完整的书册均应该包含且仅包含一本书、一本练习册和一份答案,然而现在全都乱做了一团。许多书上面的字迹都已经模糊了,然而 HansBug 还是可以大致判断这是一本书还是练习册或答案,并且能够大致知道一本书和答案以及一本书和练习册的对应关系(即仅仅知道某书和某答案、某书和某练习册有可能相对应,除此以外的均不可能对应)。既然如此,HansBug 想知道在这样的情况下,最多可能同时组合成多少个完整的书册。


输入格式


第一行包含三个正整数 �1,�2,�3N1,N2,N3,分别表示书的个数、练习册的个数和答案的个数。


第二行包含一个正整数 �1M1,表示书和练习册可能的对应关系个数。


接下来 �1M1 行每行包含两个正整数 �,�x,y,表示第 �x 本书和第 �y 本练习册可能对应。(1≤�≤�11≤x≤N1,1≤�≤�21≤y≤N2)


第 �1+3M1+3 行包含一个正整数 �2M2,表述书和答案可能的对应关系个数。


接下来 �2M2 行每行包含两个正整数 �,�x,y,表示第 �x 本书和第 �y 本答案可能对应。(1≤�≤�11≤x≤N1,1≤�≤�31≤y≤N3)


输出格式


输出包含一个正整数,表示最多可能组成完整书册的数目。


输入输出样例


输入 #1复制


5 3 4

5

4 3

2 2

5 2

5 1

5 3

5

1 3

3 1

2 2

3 3

4 3

输出 #1复制


2


说明/提示


样例说明:


如题,�1=5N1=5,�2=3N2=3,�3=4N3=4,表示书有 55 本、练习册有 33 本、答案有 44 本。


�1=5M1=5,表示书和练习册共有 55 个可能的对应关系,分别为:书 44 和练习册 33 、书 22 和练习册 22 、书 55 和练习册 22 、书 55 和练习册 11 以及书 55 和练习册 33。


�2=5M2=5,表示数和答案共有 55 个可能的对应关系,分别为:书 11 和答案 33、书 33 和答案 11、书 22 和答案 22、书 33 和答案 33 以及书 44 和答案 33。


所以,以上情况的话最多可以同时配成两个书册,分别为:书 22 练习册 22 答案 22、书 44 练习册 33 答案 33。


数据规模:


f9f58f6832ac5465ffaf53f2724b450d_ac7cc776c14f4af9fc6a9f6286f27021.png


对于数据点 1,2,31,2,3,1≤�1,�2≤201≤M1,M2≤20。


对于数据点 4∼104∼10,1≤�1,�2≤200001≤M1,M2≤20000。


题解


从每本作业本向某些书连一条边,从每本书向某些答案连一条边,区分一下三类本子,再建超级源点、超级汇点就行了,一步一步打。


(爆10专用)你爆10大概是因为这类数据能把你卡掉。


1 2 2 2 1 2 1 1 2 1 2 1 1(答案是1,你会打2)解决方法是把每本书的点容量设为1,然后拆点,把每本书对应的点拆成两个点,中间添一条容量为1的边。


(爆30专用)数组开大10倍。


#include<bits/stdc++.h>
using namespace std;
int la[200002],en[2000001],rev[2000001],c[2000001],ne[2000001];
int q[200003],level[200002],now[200002];
int n,n1,n2,n3,m1,m2,top;
void bfs(int s){
    memset(level,-1,sizeof(level));
    memset(q,0,sizeof(q));
    int h=0,t=1;
    q[1]=s;
    level[s]=0;
    while (h<t)
      for (int i=la[q[++h]];i;i=ne[i])
        if (c[i]>0&&level[en[i]]<0){
            level[en[i]]=level[q[h]]+1;
            q[++t]=en[i];
        }
}
int dfs(int u,int t,int f){
    if (u==t) return f;
    for (int &i=now[u];i>0;i=ne[i])
      if (c[i]>0&&level[u]<level[en[i]]){
          int d=dfs(en[i],t,min(f,c[i]));
          if (d>0){
              c[i]-=d;
              c[rev[i]]+=d;
              return d;
          }
      }
    return 0;
}
int max_flow(int s,int t){
    int flow=0;
    while (1){
        bfs(s);
        if (level[t]<0) return flow;
        for (int i=0;i<=n+n1;i++) now[i]=la[i];
        int f;
        while (f=dfs(s,t,1000000000)>0) flow+=f; 
    }
}
void add(int x,int y,int z){
    ne[++top]=la[x];
    en[top]=y;
    c[top]=z;
    rev[top]=top+1;
    la[x]=top;
    ne[++top]=la[y];
    en[top]=x;
    c[top]=0;
    rev[top]=top-1;
    la[y]=top;
}
int main(){
    scanf("%d%d%d",&n1,&n2,&n3);
    n=n1+n2+n3;
    scanf("%d",&m1);
    for (int i=1;i<=m1;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(b+n1,a,1);
    }
    scanf("%d",&m2);
    for (int i=1;i<=m2;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a+n,b+n1+n2,1);
    }
    for (int i=1;i<=n1;i++) add(i,i+n,1);
    for (int i=1;i<=n2;i++) add(0,i+n1,1);
    for (int i=1;i<=n3;i++) add(i+n1+n2,n+n1+1,1);
    int ans=max_flow(0,n+n1+1);
    printf("%d",ans);
    return 0;
}

相关文章
|
5月前
【洛谷】P2004 领地选择
洛谷 P2004 领地选择
47 2
【洛谷】P2004 领地选择
|
5月前
【洛谷】P1163 银行贷款
洛谷P1163 银行贷款
53 0
【洛谷】P1163 银行贷款
|
5月前
|
人工智能
【洛谷】P2678 跳石头
洛谷 P2678 跳石头
38 0
【洛谷】P2678 跳石头
|
算法
《蓝桥杯每日一题》二分·AcWing 1460. 我在哪?
《蓝桥杯每日一题》二分·AcWing 1460. 我在哪?
58 0
《蓝桥杯每日一题》递推·AcWing 3777. 砖块
《蓝桥杯每日一题》递推·AcWing 3777. 砖块
80 0
|
机器学习/深度学习
《蓝桥杯每日一题》背包dp·AcWing3382. 整数拆分
《蓝桥杯每日一题》背包dp·AcWing3382. 整数拆分
76 0
洛谷1102 A-B 暴力法
判断第 i 个数和 i 之后的每一个数的绝对值是否等于目标结果
洛谷P1679-神奇的四次方数(完全背包)
洛谷P1679-神奇的四次方数(完全背包)
洛谷P1679-神奇的四次方数(完全背包)
洛谷P1616-疯狂的采药(完全背包)
洛谷P1616-疯狂的采药(完全背包)