• P4251 [SCOI2015]小凸玩矩阵


     题解:求第K大,要求第K大最小,一般都是二分答案

    然后不是同一行同一列,显然又是匹配问题

    考虑<=x的值,要大于等于n-k+1

    然后不断找最小答案,

    每次判断答案把图给clear掉,然后重新建图就行了

    建模的问题的话,考虑是行和列作为点,然后点作为边,这样考虑就行了,把小于x的元素建边就行了 ,

    因为他最多选min(n,m)个点,所以每个行和列只能用一次

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=1e9+5;
    const int maxn=505;
    struct edg
    {
        int to,cap,rev;
       edg() :to(), cap(), rev(){}
      edg(int a, int  b, int  c) :to(a), cap(b), rev(c){}
    
    };
    vector<edg> G[maxn];
    int iter[maxn];
    int level[maxn];
    void add(int from,int to,int cap)
    {
        G[from].push_back(edg(to,cap,G[to].size()));
        G[to].push_back(edg(from,0,G[from].size()-1));
    }
    void bfs(int s)
    {
        memset(level,-1,sizeof(level));
        queue<int> que;
        level[s]=0;
        que.push(s);
        while(que.size()>0)
        {
            int v=que.front();
            que.pop();
            for(int i=0;i<G[v].size();i++)
            {
                edg &e=G[v][i];
                if(e.cap>0&&level[e.to]<0)
                {
                    level[e.to]=level[v]+1;
                    que.push(e.to);
                }
            }
        }
    }
    int dfs(int v,int t,int f)
    {
        if(v==t)
             return f;
        for(int &i=iter[v];i<G[v].size();i++)
        {
            edg &e=G[v][i];
            if(e.cap>0&&level[v]<level[e.to])
            {
                int d=dfs(e.to,t,min(f,e.cap));
                if(d>0)
                {
                    e.cap-=d;
                    G[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int _maxflow(int s,int t)
    {
        int flow=0;
        for( ; ;)
        {
            bfs(s);
            if(level[t]<0)return flow;
            memset(iter,0,sizeof(iter));
            int f;
            while((f=dfs(s,t,inf))>0)
            {
                flow+=f;
            }
        }
    }
    int n,m,k;
    int a[251][251];
    int ans[90000];
    int tail=1;
    bool check(int mid)
    {   for(int i=0;i<=n+m+1;i++)
          G[i].clear();
        int x=ans[mid];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(a[i][j]<=x) add(i,j+n,1);
        for(int i=1;i<=n;i++)
        {
             add(0,i,1);
        }
        for(int i=1;i<=m;i++)
        {
           add(n+i,n+m+1,1);
        }
        return _maxflow(0,m+n+1)>=n-k+1;
    }
    int main()
    {
       cin>>n>>m>>k;
       for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
                cin>>a[i][j];
                ans[tail++]=a[i][j];
        }
       int l=1,r=tail-1;
       int anss;
       sort(ans+1,ans+tail);
       while(l<=r)
       {
           int mid=l+r>>1;
           if(check(mid))
           {
               anss=ans[mid];
               r=mid-1;
           }
           else l=mid+1;
    
       }
       cout<<anss<<endl;
    
    
    
    
    }
  • 相关阅读:
    移动应用跨平台之旅
    ReactNative之坑爹的在线安装
    关于拆箱装箱引发的类型转换报错
    Unity HDR (高动态范围 )
    Instruments如何看Mono内存分配
    Unity编辑器崩溃大全
    Unity3D获取手机存储空间
    关于构建AssetBundle哈希冲突的问题
    关于UnityWebRequest的超时讨论
    Wwise音频插件介绍
  • 原文地址:https://www.cnblogs.com/acmLLF/p/13699111.html
Copyright © 2020-2023  润新知