zoukankan      html  css  js  c++  java
  • POJ2112 Optimal Milking 二分+最大流或二分图匹配

      题目链接:http://poj.org/problem?id=2112

      和POJ2455很像,也是求最大值最小,当时就想到了二分。具体做法就是:先求出每头牛到到牛奶机器的最短路,用spfa或dijkstra(也可以用floyd直接搞)从每个牛奶机器求一次最短路即可,那么这里就可以很容易的看出来可以直接用二分图最大匹配来依次二分求解最佳值,当然也可以用网络流来求最大流,加一个超级源点和超级汇点,源点到每头牛的容量为1,每头牛到每个牛奶机器的容量为1,每个牛奶机器到汇点的容量为m,那么就可以二分来做了。这个题目用二分图做法显然更简单,更方便,但我还是用网络流模型来做了,详细见代码。

      1 //STATUS:G++_AC_125MS_1368KB
      2 #include<stdio.h>
      3 #include<stdlib.h>
      4 #include<string.h>
      5 #include<math.h>
      6 #include<iostream>
      7 #include<string>
      8 #include<algorithm>
      9 #include<vector>
     10 #include<queue>
     11 #include<stack>
     12 #include<map>
     13 using namespace std;
     14 #define LL long long
     15 #define Max(a,b) ((a)>(b)?(a):(b))
     16 #define Min(a,b) ((a)<(b)?(a):(b))
     17 #define mem(a,b) memset(a,b,sizeof(a))
     18 #define lson l,mid,rt<<1
     19 #define rson mid+1,r,rt<<1|1
     20 const int MAX=240,INF=0x3f3f3f3f;
     21 
     22 int inq[MAX],w1[MAX][MAX],w2[MAX][MAX],cap[MAX][MAX],d[MAX],cur[MAX];
     23 int n,m,k,nm,limit,maxlen,s,t;
     24 
     25 void spfa(int s)
     26 {
     27     int i,x;
     28     mem(d,0x3f);mem(inq,0);
     29     queue<int> q;
     30     q.push(s);
     31     d[s]=0;
     32     while(!q.empty()){
     33         x=q.front();q.pop();
     34         inq[x]=0;
     35         for(i=1;i<=nm;i++){
     36             if(w1[x][i] && d[x]+w1[x][i]<=d[i]){
     37                 d[i]=d[x]+w1[x][i];
     38                 if(!inq[i]){
     39                     inq[i]=1;
     40                     q.push(i);
     41                 }
     42             }
     43         }
     44     }
     45 }
     46 
     47 int bfs()
     48 {
     49     int x,i;
     50     queue<int> q;
     51     q.push(s);
     52     mem(d,0);
     53     d[s]=1;
     54     while(!q.empty()){
     55         x=q.front();q.pop();
     56         for(i=1;i<=nm;i++){
     57             if(w2[x][i] && w2[x][i]<=limit && cap[x][i] && !d[i]){
     58                 d[i]=d[x]+1;
     59                 q.push(i);
     60             }
     61         }
     62     }
     63     return d[t];
     64 }
     65 
     66 int dfs(int x,int a)
     67 {
     68     if(x==t || a==0)return a;
     69     int f,flow=0;
     70     for(int& i=cur[x];i<=nm;i++){
     71         if(w2[x][i] && w2[x][i]<=limit && d[x]+1==d[i] && (f=dfs(i,Min(a,cap[x][i])))>0){
     72             cap[x][i]-=f;
     73             cap[i][x]+=f;
     74             flow+=f;
     75             a-=f;
     76             if(!a)break;
     77         }
     78     }
     79     return flow;
     80 }
     81 
     82 int dinic()
     83 {
     84     int flow=0;
     85     while(bfs()){
     86         mem(cur,0);
     87         flow+=dfs(s,2*INF);
     88     }
     89     return flow;
     90 }
     91 
     92 int binary()
     93 {
     94     int i,j,low=1,high=maxlen,mid,t;
     95     while(low<high){
     96         mid=(low+high)>>1;
     97         mem(cap,0);
     98         for(i=n+1;i<=nm-2;i++)
     99             for(j=1;j<=n;j++)cap[i][j]=1;
    100         for(i=nm-1,j=1;j<=n;j++)cap[j][i]=k;
    101         for(i=nm,j=n+1;j<=nm-2;j++)cap[i][j]=1;
    102         limit=mid;
    103         t=dinic();
    104         if(t<m)low=mid+1;
    105         else high=mid;
    106     }
    107     return low;
    108 }
    109 
    110 int main()
    111 {
    112  //   freopen("in.txt","r",stdin);
    113     int i,j;
    114     while(~scanf("%d%d%d",&n,&m,&k))
    115     {
    116         nm=n+m;
    117         s=nm+2,t=nm+1;
    118         mem(w2,0);
    119         maxlen=-INF;
    120         for(i=1;i<=nm;i++)
    121             for(j=1;j<=nm;j++)
    122                 scanf("%d",&w1[i][j]);
    123 
    124         for(i=1;i<=n;i++){
    125             spfa(i);
    126             for(j=1;j<=nm;j++){
    127                 w2[i][j]=w2[j][i]=d[j];
    128                 if(d[j]>maxlen)maxlen=d[j];
    129             }
    130         }
    131 
    132         nm+=2;
    133         for(i=nm-1,j=1;j<=n;j++)
    134             w2[i][j]=w2[j][i]=1;
    135         for(i=nm,j=n+1;j<=nm-2;j++)
    136             w2[i][j]=w2[j][i]=1;
    137 
    138         printf("%d\n",binary());
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    element-ui 中Message 消息提示
    MYSQL 常用语法格式
    python 爬取必应每日图片
    linux:文件权限管理
    如何建立自我学习的"触发机制"?
    总有那么一些人,把自己的思想强加给别人
    linux 控制history命令历史记录
    linux apt-get 安装与卸载命令
    ubuntu16.04下 安装java8
    历史与过去是一面镜子,它照到的是你现在的自己
  • 原文地址:https://www.cnblogs.com/zhsl/p/2797718.html
Copyright © 2011-2022 走看看