• 图论(网络流):[SCOI2015]小凸玩矩阵


    Description

    小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少。
     

    Input

    第一行给出三个整数N,M,K
    接下来N行,每行M个数字,用来描述这个矩阵
     

    Output

    如题 
     

    Sample Input

    3 4 2
    1 5 6 6
    8 3 4 3
    6 8 6 3

    Sample Output

    3

    HINT

    1<=K<=N<=M<=250,1<=矩阵元素<=10^9

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <queue>
      5 using namespace std;
      6 const int maxn=100010;
      7 const int maxm=1000010;
      8 const int INF=1000000000;
      9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm];
     10 int dis[maxn],gap[maxn],path[maxn],fron[maxn];
     11 queue<int>q;
     12 
     13 struct Net_Flow{
     14     int tot;
     15     void Init(int tot_){
     16         memset(dis,0,sizeof(dis));
     17         memset(gap,0,sizeof(gap));
     18         memset(fir,0,sizeof(fir));
     19         cnt=1;tot=tot_;
     20     }
     21     void add(int a,int b,int c){
     22         nxt[++cnt]=fir[a];
     23         cap[cnt]=c;
     24         fir[a]=cnt;
     25         to[cnt]=b;
     26     }
     27     void addedge(int a,int b,int c){
     28         add(a,b,c);add(b,a,0);
     29     }
     30     bool BFS(int S,int T){
     31         dis[T]=1;q.push(T);
     32         while(!q.empty()){
     33             int x=q.front();q.pop();
     34             for(int i=fir[x];i;i=nxt[i])
     35                 if(!dis[to[i]]){
     36                     dis[to[i]]=dis[x]+1;
     37                     q.push(to[i]);
     38                 }
     39         }
     40         return dis[S];
     41     }
     42     int Max_Flow(int S,int T){
     43         if(!BFS(S,T))return 0;
     44         for(int i=0;i<tot;i++)fron[i]=fir[i];
     45         for(int i=0;i<tot;i++)gap[dis[i]]+=1;
     46         int ret=0,p=S,f,Min;
     47         while(dis[S]<=tot){
     48             if(p==T){
     49                 f=INF;
     50                 while(p!=S){
     51                     f=min(f,cap[path[p]]);
     52                     p=to[path[p]^1];
     53                 }ret+=f;p=T;
     54                 while(p!=S){
     55                     cap[path[p]]-=f;
     56                     cap[path[p]^1]+=f;
     57                     p=to[path[p]^1];
     58                 }
     59             }
     60             
     61             for(int &i=fron[p];i;i=nxt[i])
     62                 if(cap[i]&&dis[to[i]]==dis[p]-1)
     63                     {path[p=to[i]]=i;break;}
     64             
     65             if(!fron[p]){Min=tot;
     66                 if(--gap[dis[p]]==0)break;
     67                 for(int i=fir[p];i;i=nxt[i])
     68                     if(cap[i])Min=min(Min,dis[to[i]]);
     69                 gap[dis[p]=Min+1]+=1;fron[p]=fir[p];
     70                 if(p!=S)p=to[path[p]^1];    
     71             }        
     72         }
     73         return ret;
     74     }
     75 }ISAP;
     76 int a[260][260];
     77 int n,m,k,S,s1,s2,T;
     78 bool Check(int mid){
     79     ISAP.Init(2*n+m+4);
     80     ISAP.addedge(S,s1,k);
     81     ISAP.addedge(S,s2,n-k);
     82     for(int i=1;i<=n;i++){
     83         ISAP.addedge(s1,i,1);
     84         ISAP.addedge(s2,n+i,1);
     85         for(int j=1;j<=m;j++){
     86             if(i==1)
     87                 ISAP.addedge(2*n+j,T,1);
     88             if(a[i][j]>=mid)
     89                 ISAP.addedge(i,2*n+j,1);
     90             else 
     91                 ISAP.addedge(n+i,2*n+j,1);
     92         }
     93     }
     94     return ISAP.Max_Flow(S,T)==n;
     95 }
     96 
     97 int main(){
     98     int l=1,r=0;
     99     scanf("%d%d%d",&n,&m,&k);
    100     for(int i=1;i<=n;i++)
    101         for(int j=1;j<=m;j++){
    102             scanf("%d",&a[i][j]);
    103             r=max(r,a[i][j]);
    104         }
    105         
    106     T=2*n+m+3;
    107     s1=2*n+m+1;
    108     s2=2*n+m+2;    
    109     while(l<=r){
    110         int mid=(l+r)>>1;
    111         if(Check(mid))r=mid-1;
    112         else l=mid+1;
    113     }
    114     int ans=INF;
    115     for(int i=1;i<=n;i++)
    116         for(int j=1;j<=m;j++)
    117             if(a[i][j]>=l)ans=min(ans,a[i][j]);
    118     printf("%d
    ",ans);
    119     return 0;
    120 }
  • 相关阅读:
    动态SQL的注意
    关于数据库抛出异常:Incorrect string value: 'xE1x...' for column '字段名' at row 1 问题的解决方法
    让.bashrc文件在终端自动生效
    期中考试题
    RAP、Mock.js、Vue.js、Webpack
    全局变量变为局部变量 & MVC思想
    用 JS + LeanCloud 给网页添加数据库(留言功能)
    闭包的使用
    从发请求到AJAX到同源政策
    从实现HTML页面局部刷新到JSONP
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5702766.html
Copyright © 2020-2023  润新知