hdu多校第八场 1011 (hdu6667) Roundgod and Milk Tea 二分图匹配

题意:

有若干个班,每个班有些人要喝奶茶,也提供一些奶茶,一人喝一杯,但是自己班的人不能喝自己班的奶茶,求最多能有多少人喝上奶茶。

题解:

典型的二分图匹配问题,学生在左,奶茶在右,学生和非自己班的奶茶连边。

因为班级数1e6,每个班级有1e9个奶茶或学生,直接按照上述建边跑匈牙利算法会T

考虑霍尔结婚定理:点集S,点集T,边集E,其中E中的边所连两点一点在S中,一点在T中,如果S中的k个点各自经过E与T中k个不同的点相连,则称形成了一个大小为k的匹配。

k=|S|则称为完美匹配

对于S的任意子集W,如果|W|<=|Ng(W)|  <==> S有完美匹配。

其中Ng(W)为点集T中所有与W相邻(neighbor)的结点的集合。

必要性(<=)显然。

充分性(=>)...还不会,要用数学归纳法,先挖个坑。

推论:

最大匹配为对于任意S的子集W

|S|-max(|W|-|Ng(W)|)

证明不难,找一个满足霍尔定理完美匹配要求的S的子集,踢开剩下的点,就是一个完美匹配。

我们去找那个让 (|W|-|Ng(W)|)最大化的W'

对于此题,只有如下三种情况:

1,W'为空,此时所有学生都能喝到奶茶。

2,W'只包含一个班的学生,那么Ng(w)就一定是其他班的奶茶,W'想最大化必然包括这个班所有学生

3,W'包含了多个班的学生,那么Ng(w)就一定是所有的奶茶,同理,W'想最大化,必须包括所有学生,此时有多少奶茶就有多少人喝。

具体执行步骤如下:

逐个遍历班级,维护非此班级的奶茶数,检查此班同学人数是否大于非此班奶茶数。

出现0次这种情况,答案为总人数

每出现一次这种情况,答案记为原答案 和 总人数-此班人数+非此班奶茶数 的较小值

最后检查总奶茶数是否更小。

#include <bits/stdc++.h>
#define LL long long 
using namespace std;
int n;
LL a[1000006], b[1000006];

int main() {
    int T; scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) scanf("%lld%lld", a + i, b + i);
        LL totu = accumulate(a, a + n, 0ll);
        LL totv = accumulate(b, b + n, 0ll);
        LL ans;
        int flag=0;
        for (int i = 0; i < n; i++) {
            if(a[i]>totv-b[i]){
                ans=totu-a[i]+totv-b[i];
                flag++;
            }
        }
        if(flag==0){
            ans=totu;
        }
        ans=min(ans,totv);
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/isakovsky/p/11355201.html