zoukankan      html  css  js  c++  java
  • SPOJ AMR12A The Black Riders --二分+二分图最大匹配

    题意:有n个人,m个洞。每个洞能容纳一个人,每个人到每个洞需要花费一些时间。每个人到达一个洞后可以花C的时间来挖一个洞,并且最多挖一个洞,这样又能多容纳一人。求能使至少K个人进洞的最短时间。

    解法:看到n个人和m个洞,并且人要进洞容易想到二分匹配,又是求极值的问题,应该是最大匹配。由于直接求极值不好求,可以将求极值问题转化为判定问题,即二分最短时间,然后判定能否达到。判定时,如果i到j的时间小于等于mid,就将i和j连一条边,如果T[i][j]+C <= mid 说明还来得及挖洞,将i和j+m连一条边,j+m为新挖的洞,每次判定要建一次图,然后求一个最大匹配,如果最大匹配数>=k,说明mid可行,继续往下二分。直到找到答案。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 107
    
    vector<int> G[N];
    int vis[2*N],match[2*N];
    int mp[N][N];
    int n,m,k,c;
    
    int Search_Path(int s)
    {
        for(int i=0;i<G[s].size();i++)
        {
            int v = G[s][i];
            if(!vis[v])
            {
                vis[v] = 1;
                if(match[v] == -1 || Search_Path(match[v]))
                {
                    match[v] = s;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int Max_match()
    {
        memset(match,-1,sizeof(match));
        int cnt = 0;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(Search_Path(i))
                cnt++;
        }
        return cnt;
    }
    
    int check(int mid)
    {
        int i,j;
        for(i=0;i<=n;i++)
            G[i].clear();
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(mp[i][j] <= mid)
                    G[i].push_back(j);
                if(mp[i][j]+c <= mid)
                    G[i].push_back(j+m);
            }
        }
        int cnt = Max_match();
        if(cnt >= k)
            return 1;
        return 0;
    }
    
    int main()
    {
        int t,i,j;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d%d",&n,&m,&k,&c);
            int maxi = -1;
            for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                {
                    scanf("%d",&mp[i][j]);
                    maxi = max(mp[i][j],maxi);
                }
            int low = 0;
            int high = maxi;
            while(low<=high)
            {
                int mid = (low+high)/2;
                if(check(mid))
                    high = mid-1;
                else
                    low = mid+1;
            }
            printf("%d
    ",high+1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    LTS版本的解析
    symfony中twig的模板过滤器
    symfony中twig的模板载入
    symfony中twig的流程控制if,for用法
    symfony中twig的模板变量与注释
    使用Symfony 2在三小时内开发一个寻人平台
    symfony在模板中生成url
    模板中引入其他的模板
    劳务派遣有新规章,劳务工有保障了|中山劳务派
    Symfony启动过程详细学习
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3868931.html
Copyright © 2011-2022 走看看