• 网络流


        一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?
    Input

        第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。
    Output

        仅一个数,即舞曲数目的最大值。
    Sample Input
        3 0
        YYY
        YYY
        YYY
    Sample Output
        3
    Hint

        N<=50 K<=30

    题意 : 已知有 n 个男女,同时再给你一些男女之间的关系,告诉你每个男生喜欢哪几个女生,讨厌哪几个女生,并且只能和讨厌的女生最多跳 K 次舞蹈,问最终最多可以跳几次舞蹈

    思路分析 :经典的最大流构图问题,考虑每个点都连出两个点,一个表示喜欢一个是不喜欢,建图后跑一次最大流即可。

    代码示例 :

    using namespace std;
    #define ll long long
    const int maxn = 300;
    const int mod = 1e9+7;
    const double eps = 1e-9;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    
    int n, k;
    char mp[55][55];
    struct node{
        int to, flow, next;
    }e[100000];
    int head[maxn];
    int cnt = 0, s, t;
    
    void addedge(int u, int v, int w){
        e[cnt].to = v; e[cnt].flow = w; e[cnt].next = head[u]; head[u] = cnt++; 
        e[cnt].to = u; e[cnt].flow = 0; e[cnt].next = head[v]; head[v] = cnt++; 
    }
    
    int d[maxn], que[maxn];
    
    bool bfs() {
        int head1 = 0, tail1 = 1;
        memset(d, 0, sizeof(d));
        d[0] = 1, que[0] = s;
        
        while(head1 < tail1){
            int u = que[head1++];
            for(int i = head[u]; i != -1; i = e[i].next){
                int to = e[i].to;
                if (e[i].flow && !d[to]){
                    d[to] = d[u]+1;
                    que[tail1++] = to;
                }
            }
        }
        return d[t];
    }
    
    int dfs(int u, int f1){
        if (u == t) return f1;
        int f = 0;
        
        for(int i = head[u]; i != -1; i = e[i].next){
            int to = e[i].to;
            if (e[i].flow && d[to] == d[u]+1){
                int x = dfs(to, min(f1, e[i].flow));
                e[i].flow -= x; e[i^1].flow += x;
                f1 -= x; f += x;
            }
        }
        if (!f) d[u] = -2;
        return f;
    }
    
    bool check(int x){
        s = 0, t = 4*n+1;
        memset(head, -1, sizeof(head));
        cnt = 0;
        for(int i = 1; i <= n; i++){
            addedge(s, i, x);
            addedge(i, n+i, k);
            addedge(2*n+i, 3*n+i, k);
            addedge(3*n+i, t, x);
        } 
        
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if (mp[i][j] == 'Y'){
                    addedge(i, 3*n+j, 1);    
                }
                else addedge(n+i, 2*n+j, 1);
            }
        }
        
        int ret = 0;
        while(bfs()){
            ret += dfs(s, inf);
        }
        if (ret == x*n) return true;
        return false;
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        cin >> n >> k;
    
        for(int i = 1; i <= n; i++){
            scanf("%s", mp[i]+1);
        }    
        int l = 0, r = n;
        int ans;
        while(l <= r){
            int mid = (l+r)>>1;
            if (check(mid)){
                ans = mid;
                l = mid+1;
            }
            else r = mid-1;
            
            
        }
        printf("%d
    ", ans); 
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    python 登陆接口
    FTP 的搭建过程和遇到的问题
    ELK 的好文章连接
    logstash 配置文件实例
    使用 screen 管理你的远程会话
    Conda常用命令整理
    python 增加矩阵行列和维数
    26个你不知道的Python技巧
    python单下划线、双下划线、头尾双下划线说明:
    python 类方法的互相调用及self的含义
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9430852.html
Copyright © 2020-2023  润新知