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

      中文题目,题意大家都明白。

      看到“不同的行和列”就觉得要用二分匹配来做。要求最大值与最小值的差值最小,是通过枚举边的下限和上限来完成。

      枚举过程是这样的,在输入的过程可以记录下边权的最大值MAX和最小值MIN。那么他们的边权的差值的最大值为right = MAX -MIN ,最小值left =0。然后不断地增加边的下限,查找边权的差值,如果能得到完美匹配(匹配数等于n),那么就记录下这个差值。最后输出。这个搜索过程类似于最大流+二分搜索。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int N=105,INF=0x3f3f3f3f;
      8 int Map[N][N],cx[N],cy[N],dx[N],dy[N];
      9 bool bmask[N],bmap[N][N];
     10 int nx,ny,dis,ans;
     11 bool searchpath()
     12 {
     13     queue<int> q;
     14     dis=INF;
     15     memset(dx,-1,sizeof(dx));
     16     memset(dy,-1,sizeof(dy));
     17     for(int i=1;i<=nx;i++)
     18     {
     19         if(cx[i]==-1){ q.push(i); dx[i]=0; }
     20         while(!q.empty())
     21         {
     22             int u=q.front(); q.pop();
     23             if(dx[u]>dis) break;
     24             for(int v=1;v<=ny;v++)
     25             {
     26                 if(bmap[u][v]&&dy[v]==-1)
     27                 {
     28                     dy[v]= dx[u] + 1;
     29                     if(cy[v]==-1) dis=dy[v];
     30                     else
     31                     {
     32                         dx[cy[v]]= dy[v]+1;
     33                         q.push(cy[v]);
     34                     }
     35                 }
     36             }
     37         }
     38     }
     39     return dis!=INF;
     40 }
     41 int findpath(int u)
     42 {
     43     for(int v=1;v<=ny;v++)
     44     {
     45         if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+1)
     46         {
     47             bmask[v]=1;
     48             if(cy[v]!=-1&&dy[v]==dis) continue;
     49             if(cy[v]==-1||findpath(cy[v]))
     50             {
     51                 cy[v]=u; cx[u]=v;
     52                 return 1;
     53             }
     54         }
     55     }
     56     return 0;
     57 }
     58 void maxmatch()
     59 {
     60     ans=0;
     61     memset(cx,-1,sizeof(cx));
     62     memset(cy,-1,sizeof(cy));
     63     while(searchpath())
     64     {
     65         memset(bmask,0,sizeof(bmask));
     66         for(int i=1;i<=nx;i++)
     67             if(cx[i]==-1) ans+=findpath(i);
     68     }
     69 }
     70 void init()
     71 {
     72     memset(bmap,0,sizeof(bmap));
     73 }
     74 
     75 int main()
     76 {
     77     //freopen("test.txt","r",stdin);
     78     int i,j,k,n,cas,a,b;
     79     scanf("%d",&cas);
     80     while(cas--)
     81     {
     82         scanf("%d",&n);
     83         a=100,b=0;
     84         for(i=1;i<=n;i++)
     85             for(j=1;j<=n;j++){
     86                 scanf("%d",&Map[i][j]);
     87                 a=min(a,Map[i][j]);
     88                 b=max(b,Map[i][j]);
     89             }
     90         nx=ny=n;
     91         int L=0,R=b-a,mid,flag,res;
     92         while(L<=R)
     93         {
     94             mid=(L+R)/2;
     95             flag=0;
     96             for(k=a;k<=b;k++)
     97             {
     98                 for(i=1;i<=n;i++)
     99                     for(j=1;j<=n;j++)
    100                         if(Map[i][j]>=k&&Map[i][j]<=k+mid) bmap[i][j]=1;
    101                         else bmap[i][j]=0;
    102                 maxmatch();
    103                 if(ans==n) {flag=1;break;}
    104             }
    105             if(flag) {res=mid;R=mid-1;}
    106             else  L=mid+1;
    107         }
    108         printf("%d
    ",res);
    109     }
    110     return 0;
    111 }
    View Code

      

  • 相关阅读:
    线程
    开启程序子进程的方式
    multiprocess模块
    计算机网络小知识
    解决粘包问题
    网络编程相关
    反射与元类
    多态相关
    封装相关与接口
    类的继承和组合
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3989675.html
Copyright © 2011-2022 走看看