zoukankan      html  css  js  c++  java
  • 无题 II 二分图最大匹配

    题目描述

    这是一个简单的游戏,在一个n*n的矩阵中,找n个数使得这n个数都在不同的行和列里并且要求这n个数中的最大值和最小值的差值最小。

    Input

    输入一个整数T表示T组数据。
    对于每组数据第一行输入一个正整数n(1<=n<=100)表示矩阵的大小。
    接着输入n行,每行n个数x(0<=x<=100)。

    Output

    对于每组数据输出一个数表示最小差值。

    Sample Input

    1
    4
    1 1 1 1
    2 2 2 2
    3 3 3 3
    4 4 4 4
    

    Sample Output

    3
    

    分析

    因为这(n)个数都在不同的行和列,所以我们可以把这看成一个冲突条件,可以很容易地联想到二分图的最大匹配

    但是匹配的时候要修改一下匹配的条件,即用一个(mmin)和一个(mmax)限定所选的价值

    然后枚举最小差值的时候要用到二分

    代码

    #include<cstdio>
    #include<map>
    #include<iostream>
    #include<algorithm>
    #include<utility>
    #include<cstring>
    using namespace std;
    const int maxn=105;
    int a[maxn][maxn];
    int n,l,r,mids,mmax,mmin;
    bool vis[maxn];
    int match[maxn],now;
    int dfs(int xx){
        for(int i=1;i<=n;i++){
            if(now<=a[xx][i] && now+mids>=a[xx][i] && !vis[i]){
                vis[i]=1;
                if(match[i]==-1 || dfs(match[i])){
                    match[i]=xx;
                    return 1;
                }
            }
        }
        return 0;
    }
    int solve(){
        int cnt=0;
        memset(match,-1,sizeof(match));
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            cnt+=dfs(i);
        }
        if(cnt==n) return 1;
        return 0;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            mmax=-0x3f3f3f3f;
            mmin=0x3f3f3f3f;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    scanf("%d",&a[i][j]);
                    mmax=max(mmax,a[i][j]);
                    mmin=min(mmin,a[i][j]);
                }
            }
            l=0,r=mmax-mmin;
            int ans=0;
            while(l<=r){
                mids=(l+r)>>1;
                bool jud=0;
                for(now=mmin;now+mids<=mmax;now++){
                    if(solve()){
                        jud=1;
                        break;
                    } 
                }
                if(jud) ans=mids,r=mids-1;
                else l=mids+1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    JNUOJ 1187
    JNUOJ 1184
    HDU 4848
    HDU 4849
    哈夫曼树和哈弗曼编码小记
    HDU 5726
    POJ 3368 & UVA 11235
    2016江苏省CPC省赛 I
    POJ 3928
    POJ 3067
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/12879572.html
Copyright © 2011-2022 走看看